stm32 smartcard调试--不用st8024

stm32 smartcard调试--不用st8024

 

关于stm32 smartcard功能调试,官方提供的例程是配合8024芯片进行控制的。程序可从地址:http://www.pudn.com/downloads420/sourcecode/embedded/detail1781544.html下载。

经过摸索,终于调试出不用8024的程序设计。

首先确定电路连接,stm32的USART3_CK(PB12)连接到接触式IC卡的CLK端(触点4),stm32的USART3_TX(PB10)连接到接触式IC卡的IO端(触点3),然后stm32选一个GPIO作为输出连接到接触式IC卡的RST端(触点5)。ic卡的vcc和gnd当然也是要接好的了。

然后是程序设计,

1,设置时钟,关键的有三个地方,

A,在设置系统时钟为72M之后,  

  1. RCC_PCLK1Config(RCC_HCLK_Div2);  
RCC_PCLK1Config(RCC_HCLK_Div2);

    设置PCLK1频率为36M

B,

  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);  
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);

使能GPIOB总线时钟,即USART3的端口所在的IO;并使能复用时钟。

C,

  1. RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);  
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);


   使能USART3总线时钟。

2,设置IO,  

  1. GPIO_InitTypeDef GPIO_InitStructure;  
  2.   
  3.   /* Configure USART3 CK(PB.12) as alternate function push-pull */  
  4.   
  5.     GPIO_InitStructure.GPIO_Pin = SAM0_CLK;  
  6.   
  7.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
  8.   
  9.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  10.   
  11.     GPIO_Init(SAM0_Port, &GPIO_InitStructure);  
  12.   
  13.     
  14.   
  15.    /* Configure USART3 Tx (PB.10) as alternate function open-drain */  
  16.   
  17.     GPIO_InitStructure.GPIO_Pin = SAM0_IO;  
  18.   
  19.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;  
  20.   
  21.     GPIO_Init(SAM0_Port, &GPIO_InitStructure);  
  22.   
  23.    
  24.   
  25.   /* Configure Smartcard Reset  */  
  26.   
  27.     GPIO_InitStructure.GPIO_Pin = SAM0_RST;  
  28.   
  29.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
  30.   
  31. GPIO_Init(SAM0_Port, &GPIO_InitStructure);  
GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure USART3 CK(PB.12) as alternate function push-pull */

    GPIO_InitStructure.GPIO_Pin = SAM0_CLK;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(SAM0_Port, &GPIO_InitStructure);

  

   /* Configure USART3 Tx (PB.10) as alternate function open-drain */

    GPIO_InitStructure.GPIO_Pin = SAM0_IO;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;

    GPIO_Init(SAM0_Port, &GPIO_InitStructure);

 

  /* Configure Smartcard Reset  */

    GPIO_InitStructure.GPIO_Pin = SAM0_RST;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(SAM0_Port, &GPIO_InitStructure);

其中已经定义SAM0_CLK为GPIO_Pin_12,定义SAM0_Port为GPIOB,定义SAM0_RST为GPIO_Pin_11,定义SAM0_IO为GPIO_Pin_10,

3,设置USART3

  

  1. USART_InitTypeDef USART_InitStructure;  
  2.   
  3.    USART_ClockInitTypeDef USART_ClockInitStructure;  
  4.   
  5.    
  6.   
  7.      /* USART Clock set to 3.6 MHz (PCLK1 (36 MHZ) / 10) */  
  8.   
  9.   USART_SetPrescaler(USART3, 0x05);  
  10.   
  11.     
  12.   
  13.   /* USART Guard Time set to 16 Bit */  
  14.   
  15.   USART_SetGuardTime(USART3, 16);  
  16.   
  17.     
  18.   
  19.   USART_StructInit(&USART_InitStructure);  
  20.   
  21.   USART_InitStructure.USART_BaudRate = 9677;  
  22.   
  23.   USART_InitStructure.USART_WordLength = USART_WordLength_9b;  
  24.   
  25.   USART_InitStructure.USART_StopBits = USART_StopBits_1_5;  
  26.   
  27.   USART_InitStructure.USART_Parity = USART_Parity_Even;  
  28.   
  29.    
  30.   
  31.   USART_Init(USART3, &USART_InitStructure);  
  32.   
  33.    
  34.   
  35.   USART_ClockInitStructure.USART_Clock = USART_Clock_Enable;  
  36.   
  37.    
  38.   
  39.   USART_ClockInit(USART3, &USART_ClockInitStructure);    
  40.   
  41.    
  42.   
  43.   /* Enable the USART3 Parity Error Interrupt */  
  44.   
  45.   USART_ITConfig(USART3, USART_IT_PE, ENABLE);  
  46.   
  47.    
  48.   
  49.   /* Enable the USART3 Framing Error Interrupt */  
  50.   
  51.   USART_ITConfig(USART3, USART_IT_ERR, ENABLE);  
  52.   
  53.    
  54.   
  55.   /* Enable USART3 */  
  56.   
  57.   USART_Cmd(USART3, ENABLE);  
  58.   
  59.    
  60.   
  61.   /* Enable the NACK Transmission */  
  62.   
  63.   USART_SmartCardNACKCmd(USART3, ENABLE);  
  64.   
  65.    
  66.   
  67.   /* Enable the Smartcard Interface */  
  68.   
  69.   USART_SmartCardCmd(USART3, ENABLE);  
USART_InitTypeDef USART_InitStructure;

   USART_ClockInitTypeDef USART_ClockInitStructure;

 

     /* USART Clock set to 3.6 MHz (PCLK1 (36 MHZ) / 10) */

  USART_SetPrescaler(USART3, 0x05);

  

  /* USART Guard Time set to 16 Bit */

  USART_SetGuardTime(USART3, 16);

  

  USART_StructInit(&USART_InitStructure);

  USART_InitStructure.USART_BaudRate = 9677;

  USART_InitStructure.USART_WordLength = USART_WordLength_9b;

  USART_InitStructure.USART_StopBits = USART_StopBits_1_5;

  USART_InitStructure.USART_Parity = USART_Parity_Even;

 

  USART_Init(USART3, &USART_InitStructure);

 

  USART_ClockInitStructure.USART_Clock = USART_Clock_Enable;

 

  USART_ClockInit(USART3, &USART_ClockInitStructure);  

 

  /* Enable the USART3 Parity Error Interrupt */

  USART_ITConfig(USART3, USART_IT_PE, ENABLE);

 

  /* Enable the USART3 Framing Error Interrupt */

  USART_ITConfig(USART3, USART_IT_ERR, ENABLE);

 

  /* Enable USART3 */

  USART_Cmd(USART3, ENABLE);

 

  /* Enable the NACK Transmission */

  USART_SmartCardNACKCmd(USART3, ENABLE);

 

  /* Enable the Smartcard Interface */

  USART_SmartCardCmd(USART3, ENABLE);


主要配置USART3的时钟为3.6M,并且使能时钟,波特率为9677(这个值是参考官方例程的,9600也可以),字节长度为9bits(stm32中文参考资料上介绍smartcard功能时,应该设为8bits,但是设为8bits调试不成功,这个郁闷),停止位设为1.5bits,校验位设为偶校验(奇校验也可以的),其它的使能smartcard功能,都要设置好。

3,编写复位程序,ISO7816中,对IC卡的操作,重要的一步就是获取复位返回信息。

以下是我调试好的程序

  1. unsigned char PSAMInit_usart(u8 *card, u8 length)  
  2.   
  3. {  
  4.   
  5.       u8 Data;  
  6.   
  7.          //u8 card[40];   
  8.   
  9.          u8 i;  
  10.   
  11.          GPIO_WriteBit(SAM0_Port, SAM0_RST, (BitAction)0);//set the rst to low   
  12.   
  13.          for(i=0;i<length;i++)  
  14.   
  15.             card[i] = 0x00;  
  16.   
  17.          Data = 0x00;  
  18.   
  19.          for(i=0;i<length;i++)//for delay   
  20.   
  21.             Data = 0x00;  
  22.   
  23.          GPIO_WriteBit(SAM0_Port, SAM0_RST,(BitAction)1);//set the rst to high   
  24.   
  25.          for (i = 0; i < length; i++)//get the atr   
  26.   
  27.       {  
  28.   
  29.         if((USART_ByteReceive(&Data, SC_Receive_Timeout)) == SUCCESS)  
  30.   
  31.         {  
  32.   
  33.           card[i] = Data;  
  34.   
  35.         }  
  36.   
  37.       }  
  38.   
  39.          if(card[0])  
  40.   
  41.          {  
  42.   
  43.             return 1;  
  44.   
  45.    
  46.   
  47.          }  
  48.   
  49.          else  
  50.   
  51.             return 0;  
  52.   
  53. }  
unsigned char PSAMInit_usart(u8 *card, u8 length)

{

      u8 Data;

         //u8 card[40];

         u8 i;

         GPIO_WriteBit(SAM0_Port, SAM0_RST, (BitAction)0);//set the rst to low

         for(i=0;i<length;i++)

            card[i] = 0x00;

         Data = 0x00;

         for(i=0;i<length;i++)//for delay

            Data = 0x00;

         GPIO_WriteBit(SAM0_Port, SAM0_RST,(BitAction)1);//set the rst to high

         for (i = 0; i < length; i++)//get the atr

      {

        if((USART_ByteReceive(&Data, SC_Receive_Timeout)) == SUCCESS)

        {

          card[i] = Data;

        }

      }

         if(card[0])

         {

            return 1;

 

         }

         else

            return 0;

}


这个子函数是复位子函数。

然后参考官方例程中,smartcard.c中的第62行的函数SC_Handler函数,将其中第107行调用的函数SC_AnswerReq(SCState, &SC_ATR_Table[0], 40);改为,自己编写的复位函数,

  1. temp_flag = PSAMInit_usart(&SC_ATR_Table[0], 40);  
  2.   
  3.                      if(temp_flag == 0x01)  
  4.   
  5.                         *SCState = SC_ACTIVE;  
  6.   
  7.                   else  
  8.   
  9.                         *SCState = SC_POWER_OFF;   
temp_flag = PSAMInit_usart(&SC_ATR_Table[0], 40);

                     if(temp_flag == 0x01)

                        *SCState = SC_ACTIVE;

                  else

                        *SCState = SC_POWER_OFF; 


然后在测试程序中调用SC_Handler函数,即可调试。

测试程序如下

  

  1. SC_State SCState;// = SC_POWER_OFF;   
  2.   
  3.        u8 i;  
  4.   
  5.        SCState = SC_POWER_ON;  
  6.   
  7.    
  8.   
  9.     SC_ADPU.Header.CLA = 0x00;  
  10.   
  11.     SC_ADPU.Header.INS = SC_GET_A2R;  
  12.   
  13.     SC_ADPU.Header.P1 = 0x00;  
  14.   
  15.     SC_ADPU.Header.P2 = 0x00;  
  16.   
  17.     SC_ADPU.Body.LC = 0x00;  
  18.   
  19.      
  20.   
  21.     while(SCState != SC_ACTIVE_ON_T0)   
  22.   
  23.     {  
  24.   
  25.       SC_Handler(&SCState, &SC_ADPU, &SC_Responce);  
  26.   
  27.     }  
  28.   
  29.    
  30.   
  31.     /* Apply the Procedure Type Selection (PTS) */  
  32.   
  33. SC_PTSConfig();  
SC_State SCState;// = SC_POWER_OFF;

       u8 i;

       SCState = SC_POWER_ON;

 

    SC_ADPU.Header.CLA = 0x00;

    SC_ADPU.Header.INS = SC_GET_A2R;

    SC_ADPU.Header.P1 = 0x00;

    SC_ADPU.Header.P2 = 0x00;

    SC_ADPU.Body.LC = 0x00;

   

    while(SCState != SC_ACTIVE_ON_T0) 

    {

      SC_Handler(&SCState, &SC_ADPU, &SC_Responce);

    }

 

    /* Apply the Procedure Type Selection (PTS) */

SC_PTSConfig();


这其中的变量定义,宏定义,都是官方例程中的。

在函数PSAMInit_usart调用完之后,即可看到SC_ATR_Table数组中得到的复位返回信息。

然后是SC_PTSConfig();(smartcard.c第202行)这个函数的修改,主要是要根据SC_ATR_Table返回信息中的第3个字节(即ISO7816中所说TA1),来修改串口波特率,程序中208到284行,是发送并接收PTS,根据本人测试,有些卡可以完全一步一步通过这个过程,有些卡是不行的,但是后面的

  1. if(PTSConfirmStatus == 0x01)  
  2.   
  3.       {  
  4.   
  5.         workingbaudrate = apbclock * D_Table[(SC_A2R.T[0] & (u8)0x0F)];  
  6.   
  7.         workingbaudrate /= F_Table[((SC_A2R.T[0] >> 4) & (u8)0x0F)];  
  8.   
  9.         USART_StructInit(&USART_InitStructure);  
  10.   
  11.         USART_InitStructure.USART_BaudRate = workingbaudrate;  
  12.   
  13.         USART_InitStructure.USART_WordLength = USART_WordLength_9b;  
  14.   
  15.         USART_InitStructure.USART_StopBits = USART_StopBits_1_5;  
  16.   
  17.         USART_InitStructure.USART_Parity = USART_Parity_Even;  
  18.   
  19.         USART_InitStructure.USART_Clock = USART_Clock_Enable;  
  20.   
  21.         USART_Init(USART3, &USART_InitStructure);  
  22.   
  23.       }  
if(PTSConfirmStatus == 0x01)

      {

        workingbaudrate = apbclock * D_Table[(SC_A2R.T[0] & (u8)0x0F)];

        workingbaudrate /= F_Table[((SC_A2R.T[0] >> 4) & (u8)0x0F)];

        USART_StructInit(&USART_InitStructure);

        USART_InitStructure.USART_BaudRate = workingbaudrate;

        USART_InitStructure.USART_WordLength = USART_WordLength_9b;

        USART_InitStructure.USART_StopBits = USART_StopBits_1_5;

        USART_InitStructure.USART_Parity = USART_Parity_Even;

        USART_InitStructure.USART_Clock = USART_Clock_Enable;

        USART_Init(USART3, &USART_InitStructure);

      }


这一段程序是必须要执行的,否则,以后的调试就没有返回值了。所以可以去掉if(PTSConfirmStatus == 0x01)这一句。这个设置好之后,可以根据不同的内部协议进行通信了,手机卡也好,电话卡也好,不同的卡,内部协议不一样,但是发送命令、数据,接收返回数据都可以,将SC_ADPU这个结构体赋值之后,调用SC_Handler(&SCState, &SC_ADPU, &SC_Responce);这个函数。当SCState为SC_ACTIVE_ON_T0时,就可以发送命令,并接收返回值了。

 

原文:

http://blog.csdn.net/taot2009/article/details/7304060

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值