你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 RC522串口驱动程序

[复制链接]
STMCU小助手 发布时间:2021-7-12 13:20
rc522作为使用非常多的读写卡芯片,使用SPI芯片读写应用已经非常广了。但有些时候我们只有串口可以使用,或者我们觉得串口使用更加方便,那么就必须要编写串口的驱动程序。不过很难找到可以直接使用的串口程序。所以在此将我这边写好的串口驱动写好如下:


直接上代码
下面是RC522.C的驱动文件。支持读写卡号8位数据。rc522用的是stm32 的串口3,调试显示是串口1;
  1. <font face="微软雅黑" size="3">#include "rc522.h"
  2. #include "delay.h"
  3. /
  4. //MF522命令字
  5. /
  6. #define PCD_IDLE              0x00               //取消当前命令
  7. #define PCD_CALCCRC           0x03               //CRC计算
  8. #define PCD_TRANSMIT          0x04               //发送数据
  9. #define PCD_RECEIVE           0x08               //接收数据
  10. #define PCD_TRANSCEIVE        0x0C               //发送并接收数据
  11. #define PCD_AUTHENT           0x0E               //验证密钥
  12. #define PCD_RESETPHASE        0x0F               //复位

  13. /
  14. //Mifare_One卡片命令字
  15. /
  16. #define PICC_REQIDL           0x26               //寻天线区内未进入休眠状态
  17. #define PICC_REQALL           0x52               //寻天线区内全部卡
  18. #define PICC_ANTICOLL1        0x93               //防冲撞
  19. #define PICC_ANTICOLL2        0x95               //防冲撞
  20. #define PICC_AUTHENT1A        0x60               //验证A密钥
  21. #define PICC_AUTHENT1B        0x61               //验证B密钥
  22. #define PICC_READ             0x30               //读块
  23. #define PICC_WRITE            0xA0               //写块
  24. #define PICC_DECREMENT        0xC0               //扣款
  25. #define PICC_INCREMENT        0xC1               //充值
  26. #define PICC_RESTORE          0xC2               //调块数据到缓冲区
  27. #define PICC_TRANSFER         0xB0               //保存缓冲区中数据
  28. #define PICC_HALT             0x50               //休眠

  29. /
  30. //MF522 FIFO长度定义
  31. /
  32. #define DEF_FIFO_LENGTH       64                 //FIFO size=64byte
  33. #define MAXRLEN  18

  34. /
  35. //MF522寄存器定义
  36. /
  37. // PAGE 0
  38. #define     RFU00                 0x00   
  39. #define     CommandReg            0x01   
  40. #define     ComIEnReg             0x02   
  41. #define     DivlEnReg             0x03   
  42. #define     ComIrqReg             0x04   
  43. #define     DivIrqReg             0x05
  44. #define     ErrorReg              0x06   
  45. #define     Status1Reg            0x07   
  46. #define     Status2Reg            0x08   
  47. #define     FIFODataReg           0x09
  48. #define     FIFOLevelReg          0x0A
  49. #define     WaterLevelReg         0x0B
  50. #define     ControlReg            0x0C
  51. #define     BitFramingReg         0x0D
  52. #define     CollReg               0x0E
  53. #define     RFU0F                 0x0F
  54. // PAGE 1     
  55. #define     RFU10                 0x10
  56. #define     ModeReg               0x11
  57. #define     TxModeReg             0x12
  58. #define     RxModeReg             0x13
  59. #define     TxControlReg          0x14
  60. #define     TxAutoReg             0x15
  61. #define     TxSelReg              0x16
  62. #define     RxSelReg              0x17
  63. #define     RxThresholdReg        0x18
  64. #define     DemodReg              0x19
  65. #define     RFU1A                 0x1A
  66. #define     RFU1B                 0x1B
  67. #define     MifareReg             0x1C
  68. #define     RFU1D                 0x1D
  69. #define     RFU1E                 0x1E
  70. #define     SerialSpeedReg        0x1F
  71. // PAGE 2   
  72. #define     RFU20                 0x20  
  73. #define     CRCResultRegM         0x21
  74. #define     CRCResultRegL         0x22
  75. #define     RFU23                 0x23
  76. #define     ModWidthReg           0x24
  77. #define     RFU25                 0x25
  78. #define     RFCfgReg              0x26
  79. #define     GsNReg                0x27
  80. #define     CWGsCfgReg            0x28
  81. #define     ModGsCfgReg           0x29
  82. #define     TModeReg              0x2A
  83. #define     TPrescalerReg         0x2B
  84. #define     TReloadRegH           0x2C
  85. #define     TReloadRegL           0x2D
  86. #define     TCounterValueRegH     0x2E
  87. #define     TCounterValueRegL     0x2F
  88. // PAGE 3      
  89. #define     RFU30                 0x30
  90. #define     TestSel1Reg           0x31
  91. #define     TestSel2Reg           0x32
  92. #define     TestPinEnReg          0x33
  93. #define     TestPinValueReg       0x34
  94. #define     TestBusReg            0x35
  95. #define     AutoTestReg           0x36
  96. #define     VersionReg            0x37
  97. #define     AnalogTestReg         0x38
  98. #define     TestDAC1Reg           0x39  
  99. #define     TestDAC2Reg           0x3A   
  100. #define     TestADCReg            0x3B   
  101. #define     RFU3C                 0x3C   
  102. #define     RFU3D                 0x3D   
  103. #define     RFU3E                 0x3E   
  104. #define     RFU3F                                    0x3F

  105. /
  106. //和MF522通讯时返回的错误代码
  107. /
  108. #define         MI_OK                 0
  109. #define         MI_NOTAGERR           (1)
  110. #define         MI_ERR                (2)

  111. #define        SHAQU1                0X01
  112. #define        KUAI4                0X04
  113. #define        KUAI7                0X07
  114. #define        REGCARD                0xa1
  115. #define        CONSUME                0xa2
  116. #define READCARD        0xa3
  117. #define ADDMONEY        0xa4

  118. //==============================================================================================
  119. void UART3_init(void)/*串口3MC20通信*/
  120. {
  121.         GPIO_InitTypeDef GPIO_InitStructure;
  122.     USART_InitTypeDef USART_InitStructure;
  123.    
  124.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
  125.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3 , ENABLE);        
  126.         USART_DeInit(USART3);  //复位串口3
  127.    
  128.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 ;
  129.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
  130.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  131.     GPIO_Init(GPIOB, &GPIO_InitStructure);

  132.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ;
  133.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  134.     GPIO_Init(GPIOB, &GPIO_InitStructure);

  135.     USART_InitStructure.USART_BaudRate = 9600;
  136.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  137.     USART_InitStructure.USART_StopBits = USART_StopBits_1;
  138.     USART_InitStructure.USART_Parity = USART_Parity_No;
  139.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  140.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  141.        
  142.     USART_Init(USART3, &USART_InitStructure);
  143.     USART_Cmd(USART3, ENABLE);
  144. }
  145. /***********************RC522 函数宏定义**********************/
  146. u8 UART3_ReadWriteByte(u8 TxData)
  147. {               
  148.         while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET||USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET) {}                          
  149.         USART_SendData(USART3,TxData);
  150.         delay_ms(5);
  151.         return         USART_ReceiveData(USART3);                    
  152. }

  153. //==============================================================================================

  154. void  M500PcdConfigISOType( u8 type );          //工作方式
  155. void  PcdReset( void );                               //复位
  156. char  PcdRequest( u8 req_code, u8 * pTagType ); //寻卡
  157. char  PcdAnticoll( u8 * pSnr);                  //读卡号

  158. char  PcdSelect( u8 * pSnr );
  159. char  PcdAuthState( u8 ucAuth_mode, u8 ucAddr, u8 * pKey, u8 * pSnr );

  160. char  PcdWrite( u8 ucAddr, u8 * pData );
  161. char  PcdRead( u8 ucAddr, u8 * pData );

  162. void PcdAntennaOn ( void );
  163. void PcdAntennaOff ( void );

  164. void RC522_Init(void)
  165. {
  166.         UART3_init();//初始化spi3
  167.         delay_ms(1000);
  168.     PcdReset();
  169.     M500PcdConfigISOType ( 'A' );//设置工作方式
  170. }

  171. //
  172. // M1卡分为16个扇区,每个扇区由四个块(块0、块1、块2、块3)组成
  173. // 将16个扇区的64个块按绝对地址编号为:0~63
  174. // 第0个扇区的块0(即绝对地址0块),用于存放厂商代码,已经固化不可更改
  175. // 每个扇区的块0、块1、块2为数据块,可用于存放数据
  176. // 每个扇区的块3为控制块(绝对地址为:块3、块7、块11.....)包括密码A,存取控制、密码B等

  177. /*全局变量*/
  178. unsigned char CT[2];//卡类型
  179. unsigned char SN[4]; //卡号
  180. unsigned char RFID[16];                        //存放RFID
  181. unsigned char total=0;
  182. u8 KEY[6]={0xff,0xff,0xff,0xff,0xff,0xff};
  183. u8 AUDIO_OPEN[6] = {0xAA, 0x07, 0x02, 0x00, 0x09, 0xBC};
  184. unsigned char RFID1[16]={0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x07,0x80,0x29,0xff,0xff,0xff,0xff,0xff,0xff};
  185. /*函数声明*/
  186. unsigned char status;
  187. unsigned char s=0x08;

  188. /**************************************************************************************
  189. * 函数名:WriteRawRC 描述  :写RC522寄存器输入 :ucAddress,寄存器地址 ucValue,写入寄存器的值
  190. */
  191. void WriteRawRC ( u8 ucAddress, u8 ucValue )
  192. {  
  193.         u8 ch = UART3_ReadWriteByte (ucAddress& 0x3F);  // 写入寄存器地址(最低6位为实际地址,次高为保留为0,最高位为1)
  194.         if(ch != ucAddress) printf("not equal!!\r\n");
  195.         UART3_ReadWriteByte (ucValue);
  196. }
  197. /**************************************************************************************
  198. * 函数名:ReadRawRC 读取寄存器的当前值
  199. */
  200. u8 ReadRawRC ( u8 ucAddress )
  201. {
  202.         return UART3_ReadWriteByte((ucAddress&0x3F) | 0x80);
  203. }
  204. /**************************************************************************************
  205. * 函数名:ClearBitMask 对RC522寄存器清位
  206. */
  207. void ClearBitMask ( u8 ucReg, u8 ucMask )  
  208. {
  209.     u8 ucTemp;
  210.     ucTemp = ReadRawRC ( ucReg );
  211.     WriteRawRC ( ucReg, ucTemp & ( ~ ucMask) );  // clear bit mask
  212. }
  213. /**************************************************************************************
  214. * 函数名:SetBitMask 对RC522寄存器置位
  215. */
  216. void SetBitMask ( u8 ucReg, u8 ucMask )  
  217. {
  218.     u8 ucTemp;
  219.     ucTemp = ReadRawRC ( ucReg );
  220.     WriteRawRC ( ucReg, ucTemp | ucMask );         // set bit mask
  221. }
  222. /**************************************************************************************
  223. * 函数名:PcdAntennaOn 开启天线
  224. */
  225. void PcdAntennaOn ( void )
  226. {
  227.     u8 uc;
  228.     uc = ReadRawRC ( TxControlReg );
  229.     if ( ! ( uc & 0x03 ) )
  230.                         SetBitMask(TxControlReg, 0x03);
  231. }
  232. /**************************************************************************************
  233. * 函数名:PcdAntennaOff 关闭天线
  234. */
  235. void PcdAntennaOff ( void )
  236. {
  237.     ClearBitMask ( TxControlReg, 0x03 );
  238. }
  239. /**************************************************************************************
  240. * 描述  :设置RC522的工作方式 ucType,工作方式
  241. */
  242. void M500PcdConfigISOType ( u8 ucType )
  243. {
  244.         if ( ucType == 'A')                     //ISO14443_A
  245.   {
  246.                 ClearBitMask ( Status2Reg, 0x08 );
  247.         WriteRawRC ( ModeReg, 0x3D );//3F
  248.                 WriteRawRC ( RxSelReg, 0x86 );//84
  249.                 WriteRawRC( RFCfgReg, 0x7F );   //4F
  250.                 WriteRawRC( TReloadRegL, 30 );//tmoLength);// TReloadVal = 'h6a =tmoLength(dec)
  251.                 WriteRawRC ( TReloadRegH, 0 );
  252.                 WriteRawRC ( TModeReg, 0x8D );
  253.                 WriteRawRC ( TPrescalerReg, 0x3E );
  254.                 delay_us ( 2 );
  255.                 PcdAntennaOn ();//开天线
  256.    }
  257. }
  258. /**************************************************************************************
  259. * 函数名:PcdComMF522
  260. * 描述  :通过RC522和ISO14443卡通讯
  261. * 输入  :ucCommand,RC522命令字
  262. *         pInData,通过RC522发送到卡片的数据
  263. *         ucInLenByte,发送数据的字节长度
  264. *         pOutData,接收到的卡片返回数据
  265. *         pOutLenBit,返回数据的位长度
  266. * 返回  : 状态值 MI_OK,成功
  267. */
  268. char PcdComMF522 ( u8 ucCommand, u8 * pInData, u8 ucInLenByte, u8 * pOutData, u32 * pOutLenBit )               
  269. {
  270.     char cStatus = MI_ERR;
  271.     u8 ucIrqEn   = 0x00;
  272.     u8 ucWaitFor = 0x00;
  273.     u8 ucLastBits;
  274.     u8 ucN;
  275.     u32 ul;
  276.     switch ( ucCommand )
  277.     {
  278.        case PCD_AUTHENT:                //Mifare认证
  279.           ucIrqEn   = 0x12;                //允许错误中断请求ErrIEn  允许空闲中断IdleIEn
  280.           ucWaitFor = 0x10;                //认证寻卡等待时候 查询空闲中断标志位
  281.           break;
  282.                          
  283.        case PCD_TRANSCEIVE:                //接收发送 发送接收
  284.           ucIrqEn   = 0x77;                //允许TxIEn RxIEn IdleIEn LoAlertIEn ErrIEn TimerIEn
  285.           ucWaitFor = 0x30;                //寻卡等待时候 查询接收中断标志位与 空闲中断标志位
  286.           break;
  287.                          
  288.        default:
  289.          break;
  290.     }
  291.     WriteRawRC ( ComIEnReg, ucIrqEn | 0x80 );                //IRqInv置位管脚IRQ与Status1Reg的IRq位的值相反
  292.     ClearBitMask ( ComIrqReg, 0x80 );                                //Set1该位清零时,CommIRqReg的屏蔽位清零
  293.     WriteRawRC ( CommandReg, PCD_IDLE );                        //写空闲命令
  294.     SetBitMask ( FIFOLevelReg, 0x80 );                                //置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除
  295.    
  296.     for ( ul = 0; ul < ucInLenByte; ul ++ )
  297.                   WriteRawRC ( FIFODataReg, pInData [ ul ] );            //写数据进FIFOdata
  298.                        
  299.     WriteRawRC ( CommandReg, ucCommand );                                        //写命令
  300.    
  301.     if ( ucCommand == PCD_TRANSCEIVE )
  302.                         SetBitMask(BitFramingReg,0x80);                                  //StartSend置位启动数据发送 该位与收发命令使用时才有效
  303.    
  304.     ul = 1000;//根据时钟频率调整,操作M1卡最大等待时间25ms
  305.                
  306.     do                                                                                                                 //认证 与寻卡等待时间       
  307.     {
  308.          ucN = ReadRawRC ( ComIrqReg );                                                //查询事件中断
  309.          ul --;
  310.     }
  311.         while ( ( ul != 0 ) && ( ! ( ucN & 0x01 ) ) && ( ! ( ucN & ucWaitFor ) ) );                //退出条件i=0,定时器中断,与写空闲命令
  312.                
  313.     ClearBitMask ( BitFramingReg, 0x80 );                                        //清理允许StartSend位
  314.                
  315.     if ( ul != 0 )
  316.     {
  317.                 if ( ! (( ReadRawRC ( ErrorReg ) & 0x1B )) )                        //读错误标志寄存器BufferOfI CollErr ParityErr ProtocolErr
  318.                 {
  319.                         cStatus = MI_OK;
  320.                         if ( ucN & ucIrqEn & 0x01 )                                        //是否发生定时器中断
  321.                           cStatus = MI_NOTAGERR;   
  322.                         if ( ucCommand == PCD_TRANSCEIVE )
  323.                         {
  324.                                 ucN = ReadRawRC ( FIFOLevelReg );                        //读FIFO中保存的字节数
  325.                                 ucLastBits = ReadRawRC ( ControlReg ) & 0x07;        //最后接收到得字节的有效位数
  326.                                 if ( ucLastBits )
  327.                                         * pOutLenBit = ( ucN - 1 ) * 8 + ucLastBits;           //N个字节数减去1(最后一个字节)+最后一位的位数 读取到的数据总位数
  328.                                 else
  329.                                         * pOutLenBit = ucN * 8;                                           //最后接收到的字节整个字节有效
  330.                                 if ( ucN == 0 )       
  331.                     ucN = 1;   
  332.                                 if ( ucN > MAXRLEN )
  333.                                         ucN = MAXRLEN;   
  334.                                 for ( ul = 0; ul < ucN; ul ++ )
  335.                                   pOutData [ ul ] = ReadRawRC ( FIFODataReg );   
  336.                         }               
  337.         }
  338.                         else
  339.                                 cStatus = MI_ERR;   
  340.                         //printf("ErrorReg=%d\r\n",ErrorReg);
  341.     }
  342.    SetBitMask ( ControlReg, 0x80 );           // stop timer now
  343.    WriteRawRC ( CommandReg, PCD_IDLE );
  344.    return cStatus;
  345. }
  346. //=========================================RC522_Handel================================================//
  347. bool RC522_READ(u8 * str)
  348. {
  349.     status = PcdRequest(PICC_REQALL,CT);//寻卡
  350.     if(status==MI_OK)//寻卡成功
  351.     {
  352.          status=MI_ERR;
  353.          status = PcdAnticoll(SN);//防冲撞               
  354.     }
  355.     if (status==MI_OK)//防衝撞成功
  356.     {
  357.         status=MI_ERR;               
  358.         status =PcdSelect(SN);
  359.     }
  360.     if(status==MI_OK)//選卡成功
  361.     {
  362.         status=MI_ERR;
  363.         status =PcdAuthState(0x60,0x09,KEY,SN);
  364.      }
  365.         if(status==MI_OK)//驗證成功
  366.     {
  367.         status=MI_ERR;
  368.         status=PcdRead(s,RFID);
  369.     }
  370.     if(status==MI_OK)//讀卡成功
  371.     {
  372.         status=MI_ERR;
  373.                 memset(str,0,10);
  374.                 memcpy(str,RFID,9); //显示卡的ID号
  375.                 return 1;
  376.    }
  377.    
  378.   return 0;
  379. }
  380. //=========================================RC522_Handel================================================//
  381. bool RC522_WRITE(u8 * msg)
  382. {
  383.         if(msg == NULL)return false;
  384.     status = PcdRequest(PICC_REQALL,CT);//寻卡
  385.     if(status==MI_OK)//寻卡成功
  386.     {
  387.          status=MI_ERR;
  388.          status = PcdAnticoll(SN);//防冲撞               
  389.     }
  390.     if (status==MI_OK)//防衝撞成功
  391.     {
  392.         status=MI_ERR;               
  393.         status =PcdSelect(SN);
  394.     }
  395.     if(status==MI_OK)//選卡成功
  396.     {
  397.         status=MI_ERR;
  398.         status =PcdAuthState(0x60,0x09,KEY,SN);
  399.      }
  400.    if(status==MI_OK)//驗證成功
  401.     {
  402.         status=MI_ERR;
  403.                 status=PcdWrite(s,msg);
  404.     }
  405.     if(status==MI_OK)//写卡成功
  406.                 return true;
  407.         return false;
  408. }
  409. /*********************************************************************************************************************
  410. * 函数名:PcdRequest 寻卡
  411. * 输入  :ucReq_code,寻卡方式
  412. *                   = 0x52,寻感应区内所有符合14443A标准的卡
  413. *                   = 0x26,寻未进入休眠状态的卡
  414. *         pTagType,卡片类型代码
  415. *                   = 0x4400,Mifare_UltraLight
  416. *                   = 0x0400,Mifare_One(S50)
  417. *                   = 0x0200,Mifare_One(S70)
  418. *                   = 0x0800,Mifare_Pro(X))
  419. *                   = 0x4403,Mifare_DESFire
  420. * 返回  : 状态值  MI_OK,成功
  421. */
  422. char PcdRequest ( u8 ucReq_code, u8 * pTagType )
  423. {
  424.     char cStatus;  
  425.     u8 ucComMF522Buf [ MAXRLEN ];
  426.     u32 ulLen;

  427.     ClearBitMask ( Status2Reg, 0x08 );        //清理指示MIFARECyptol单元接通以及所有卡的数据通信被加密的情况
  428.     WriteRawRC ( BitFramingReg, 0x07 );        //        发送的最后一个字节的 七位
  429.     SetBitMask ( TxControlReg, 0x03 );        //TX1,TX2管脚的输出信号传递经发送调制的13.56的能量载波信号
  430.     ucComMF522Buf [ 0 ] = ucReq_code;                //存入 卡片命令字
  431.     cStatus = PcdComMF522( PCD_TRANSCEIVE,ucComMF522Buf, 1, ucComMF522Buf, & ulLen );        //寻卡  
  432.     if ( ( cStatus == MI_OK ) && ( ulLen == 0x10 ) )        //寻卡成功返回卡类型
  433.     {   
  434.        * pTagType = ucComMF522Buf [ 0 ];
  435.        * ( pTagType + 1 ) = ucComMF522Buf [ 1 ];
  436.     }
  437.     else
  438.      cStatus = MI_ERR;
  439.     return cStatus;
  440. }

  441. /************************************************************************************************************
  442. * 函数名:PcdAnticoll 防冲撞:pSnr,卡片序列号,4字节
  443. * 返回  : 状态值 MI_OK,成功
  444. */
  445. char PcdAnticoll ( u8 * pSnr )
  446. {
  447.     char cStatus;
  448.     u8 uc, ucSnr_check = 0;
  449.     u8 ucComMF522Buf [ MAXRLEN ];
  450.         u32 ulLen;
  451.     ClearBitMask ( Status2Reg, 0x08 );                //清MFCryptol On位 只有成功执行MFAuthent命令后,该位才能置位
  452.     WriteRawRC ( BitFramingReg, 0x00);                //清理寄存器 停止收发
  453.     ClearBitMask ( CollReg, 0x80 );                        //清ValuesAfterColl所有接收的位在冲突后被清除
  454.     ucComMF522Buf [ 0 ] = 0x93;        //卡片防冲突命令
  455.     ucComMF522Buf [ 1 ] = 0x20;
  456.     cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 2, ucComMF522Buf, & ulLen);//与卡片通信
  457.     if ( cStatus == MI_OK)                //通信成功
  458.     {
  459.                 for ( uc = 0; uc < 4; uc ++ )
  460.         {
  461.             * ( pSnr + uc )  = ucComMF522Buf [ uc ];                        //读出UID
  462.             ucSnr_check ^= ucComMF522Buf [ uc ];
  463.         }       
  464.         if ( ucSnr_check != ucComMF522Buf [ uc ] )
  465.                         cStatus = MI_ERR;                     
  466.     }
  467.     SetBitMask ( CollReg, 0x80 );
  468.     return cStatus;
  469. }
  470. /************************************************************************************************************
  471. * 函数名:CalulateCRC
  472. * 描述  :用RC522计算CRC16
  473. * 输入  :pIndata,计算CRC16的数组
  474. *         ucLen,计算CRC16的数组字节长度
  475. *         pOutData,存放计算结果存放的首地址
  476. */
  477. void CalulateCRC ( u8 * pIndata, u8 ucLen, u8 * pOutData )
  478. {
  479.     u8 uc, ucN;
  480.     ClearBitMask(DivIrqReg,0x04);
  481.     WriteRawRC(CommandReg,PCD_IDLE);
  482.     SetBitMask(FIFOLevelReg,0x80);
  483.     for ( uc = 0; uc < ucLen; uc ++)
  484.             WriteRawRC ( FIFODataReg, * ( pIndata + uc ) );   
  485.     WriteRawRC ( CommandReg, PCD_CALCCRC );
  486.     uc = 0xFF;
  487.     do
  488.     {
  489.         ucN = ReadRawRC ( DivIrqReg );
  490.         uc --;
  491.     } while ( ( uc != 0 ) && ! ( ucN & 0x04 ) );
  492.                
  493.     pOutData [ 0 ] = ReadRawRC ( CRCResultRegL );
  494.     pOutData [ 1 ] = ReadRawRC ( CRCResultRegM );
  495. }

  496. /************************************************************************************************************
  497. * 函数名:PcdSelect
  498. * 描述  :选定卡片
  499. * 输入  :pSnr,卡片序列号,4字节
  500. * 返回  : 状态值
  501. *         = MI_OK,成功
  502. * 调用  :外部调用
  503. */
  504. char PcdSelect ( u8 * pSnr )
  505. {
  506.     char         ucN;
  507.     u8                 uc;
  508.         u8                 ucComMF522Buf [ MAXRLEN ];
  509.     u32          ulLen;
  510.     ucComMF522Buf [ 0 ] = PICC_ANTICOLL1;
  511.     ucComMF522Buf [ 1 ] = 0x70;
  512.     ucComMF522Buf [ 6 ] = 0;
  513.     for ( uc = 0; uc < 4; uc ++ )
  514.     {
  515.             ucComMF522Buf [ uc + 2 ] = * ( pSnr + uc );
  516.             ucComMF522Buf [ 6 ] ^= * ( pSnr + uc );
  517.     }       
  518.     CalulateCRC ( ucComMF522Buf, 7, & ucComMF522Buf [ 7 ] );
  519.     ClearBitMask ( Status2Reg, 0x08 );
  520.     ucN = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 9, ucComMF522Buf, & ulLen );
  521.     if ( ( ucN == MI_OK ) && ( ulLen == 0x18 ) )
  522.       ucN = MI_OK;  
  523.     else
  524.       ucN = MI_ERR;   
  525.     return ucN;
  526. }
  527. /************************************************************************************************************
  528. * 函数名:PcdAuthState 验证卡片密码
  529. * 输入  :ucAuth_mode,密码验证模式
  530. *                     = 0x60,验证A密钥
  531. *                     = 0x61,验证B密钥
  532. *         u8 ucAddr,块地址
  533. *         pKey,密码
  534. *         pSnr,卡片序列号,4字节
  535. * 返回  : 状态值MI_OK,成功
  536. */
  537. char PcdAuthState ( u8 ucAuth_mode, u8 ucAddr, u8 * pKey, u8 * pSnr )
  538. {
  539.     char cStatus;
  540.         u8 uc, ucComMF522Buf [ MAXRLEN ];
  541.     u32 ulLen;
  542.     ucComMF522Buf [ 0 ] = ucAuth_mode;
  543.     ucComMF522Buf [ 1 ] = ucAddr;
  544.     for ( uc = 0; uc < 6; uc ++ )
  545.             ucComMF522Buf [ uc + 2 ] = * ( pKey + uc );   
  546.     for ( uc = 0; uc < 6; uc ++ )
  547.             ucComMF522Buf [ uc + 8 ] = * ( pSnr + uc );   
  548.     cStatus = PcdComMF522 ( PCD_AUTHENT, ucComMF522Buf, 12, ucComMF522Buf, & ulLen );
  549.     if ( ( cStatus != MI_OK ) || ( ! ( ReadRawRC ( Status2Reg ) & 0x08 ) ) )
  550.                 {
  551.                         if(cStatus != MI_OK)
  552.                                 printf("666");               
  553.                         else
  554.                                 printf("888");
  555.                         cStatus = MI_ERR;
  556.                 }
  557.     return cStatus;
  558. }

  559. /**********************************************************************************************
  560. * 函数名:PcdWrite B写数据到M1卡一块 NpData,写入的数据,16字节
  561. * 返回  : 状态值MI_OK,成功
  562. */
  563. char PcdWrite ( u8 ucAddr, u8 * pData )
  564. {
  565.     char cStatus;
  566.         u8 uc, ucComMF522Buf [ MAXRLEN ];
  567.     u32 ulLen;
  568.        
  569.     ucComMF522Buf [ 0 ] = PICC_WRITE;
  570.     ucComMF522Buf [ 1 ] = ucAddr;
  571.     CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );
  572.     cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, & ulLen );
  573.     if ( ( cStatus != MI_OK ) || ( ulLen != 4 ) || ( ( ucComMF522Buf [ 0 ] & 0x0F ) != 0x0A ) )
  574.       cStatus = MI_ERR;   
  575.     if ( cStatus == MI_OK )
  576.     {
  577.                 memcpy(ucComMF522Buf, pData, 16);
  578.                 for ( uc = 0; uc < 16; uc ++ )
  579.                           ucComMF522Buf [ uc ] = * ( pData + uc );  
  580.                 CalulateCRC ( ucComMF522Buf, 16, & ucComMF522Buf [ 16 ] );
  581.                 cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 18, ucComMF522Buf, & ulLen );
  582.                 if ( ( cStatus != MI_OK ) || ( ulLen != 4 ) || ( ( ucComMF522Buf [ 0 ] & 0x0F ) != 0x0A ) )
  583.                         cStatus = MI_ERR;   
  584.     }
  585.     return cStatus;
  586. }
  587. /**********************************************************************************************
  588. * 函数名:PcdRead读取M1卡一块数据  pData,读出的数据,16字节
  589. * 返回  : 状态值 MI_OK,成功
  590. */
  591. char PcdRead ( u8 ucAddr, u8 * pData )
  592. {
  593.     char cStatus;
  594.         u8 uc, ucComMF522Buf [ MAXRLEN ];
  595.     u32 ulLen;

  596.     ucComMF522Buf [ 0 ] = PICC_READ;
  597.     ucComMF522Buf [ 1 ] = ucAddr;
  598.     CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );
  599.     cStatus = PcdComMF522 (PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, & ulLen);
  600.     if ( ( cStatus == MI_OK ) && ( ulLen == 0x90 ) )
  601.     {
  602.                 for ( uc = 0; uc < 16; uc ++ )
  603.         * ( pData + uc ) = ucComMF522Buf [ uc ];   
  604.     }
  605.     else
  606.       cStatus = MI_ERR;   
  607.     return cStatus;
  608. }
  609. /**********************************************************************************************
  610. */

  611. /*
  612. * 函数名:PcdRese
  613. * 描述  :复位RC522
  614. */
  615. void PcdReset ( void )
  616. {
  617.     delay_us ( 4 );
  618.     WriteRawRC ( CommandReg, 0x0f );
  619.     while( ReadRawRC ( CommandReg ) & 0x10 );
  620.         ReadRawRC ( CommandReg );
  621.     delay_us ( 5 );
  622.     WriteRawRC ( ModeReg, 0x3D );                    //定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363
  623.     WriteRawRC ( TReloadRegL, 30 );                  //16位定时器低位   
  624.     WriteRawRC ( TReloadRegH, 0 );                            //16位定时器高位
  625.     WriteRawRC ( TModeReg, 0x8D );                                //定义内部定时器的设置
  626.     WriteRawRC ( TPrescalerReg, 0x3E );                        //设置定时器分频系数
  627.     WriteRawRC ( TxAutoReg, 0x40 );                                //调制发送信号为100%ASK       
  628. }
  629. /* 该测试用例测试中 */
  630. void test(void){
  631.         while(1){
  632.                 printf("================================\r\n");
  633.                 delay_ms(1000);
  634.                 u32 i = 0;
  635.                 while(i<0x40){
  636.                         u8 ch =  ReadRawRC(i);
  637.                         printf("%02x ",ch);
  638.                         i++;
  639.                         delay_ms(10);
  640.                         if(i%16 == 0)
  641.                                 printf("\r\n");
  642.                 }
  643.                
  644.                 static u32 t = 0;
  645.                 if(t++ == 5){
  646.                         WriteRawRC(WaterLevelReg,0x01);
  647.                         u8 ch = ReadRawRC(WaterLevelReg);
  648.                         printf("%02x\r\n",ch);
  649.                 }else if(t == 8){
  650.                         WriteRawRC(WaterLevelReg,0x02);
  651.                         u8 ch = ReadRawRC(WaterLevelReg);
  652.                         printf("%02x\r\n",ch);
  653.                 }else if(t == 12){
  654.                         WriteRawRC(WaterLevelReg,0x03);
  655.                         u8 ch = ReadRawRC(WaterLevelReg);
  656.                         printf("%02x\r\n",ch);
  657.                 }
  658.         }
  659. }</font>
复制代码
下发是头文件rc522.h
  1. <font face="微软雅黑" size="3">#ifndef _RC522_H_
  2. #define _RC522_H_
  3. #include "sys.h"
  4. bool  RC522_READ(u8 * str);                                    //读卡
  5. bool  RC522_WRITE(u8 * msg);                                //写卡
  6. void  RC522_Init(void);                     //初始化
  7. void test(void);
  8. #endif
  9. </font>
复制代码
最后是我用来测试的main文件
包含写卡,和读卡测试。亲测可以使用。

  1. <font face="微软雅黑" size="3">#include "stm32f10x.h"
  2. #include "uart.h"
  3. #include "sys.h"
  4. #include "rc522.h"

  5. int main(void)
  6. {
  7.         u8 IC[50] = {0};
  8.         delay_init();
  9.         UART1_init();
  10.         delay_ms(2000);
  11.         RC522_Init();
  12.         printf("RC522_UART_TEST...\r\n");
  13.        
  14.         printf(" 写卡开始...\r\n");
  15.         while(!RC522_WRITE((u8 *)"12121212")){};
  16.         printf(" 写卡成功...\r\n");
  17.        
  18.         while(1){
  19.                 if(RC522_READ(IC)){
  20.                         printf("%s\r\n",IC);
  21.                         delay_ms(500);
  22.                 }
  23.                 delay_ms(100);
  24.                 printf("waitting...\r\n");
  25.         }
  26. }</font>
复制代码



收藏 评论0 发布时间:2021-7-12 13:20

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版