找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5152|回复: 6
收起左侧

基于stm32F103xxx与RFID-RC522的门禁程序

  [复制链接]
ID:618513 发表于 2021-1-4 20:37 | 显示全部楼层 |阅读模式
最近用到了RFID-RC522,找了很多资料,总结了一下 顺便和大家分享分享。  再本人的项目中RFID只是用来起到刷卡开门的效果,顺带用串口打印显示ID号。 需要的朋友自行下载。
RD
连线如下:
//SPI2_SCK                         PB13
//SPI2_MISO                        PB14
//SPI2_MOSI                         PB15
//RCC522_RST                   PC4
//RCC522_SDA                   PB0
//RCC522_IRQ                         悬空(不管)


直接移植久好  驱动是全的      
  1. #include "rc522.h"

  2. //SPI2_SCK                                 PB13
  3. //SPI2_MISO                                PB14
  4. //SPI2_MOSI                         PB15
  5. //RCC522_RST(CE)  PC4
  6. //RCC522_NSS(SDA)PB0
  7. //RCC522_IRQ                         悬空

  8. void SPI2_Init(void)
  9. {
  10.         GPIO_InitTypeDef GPIO_InitStructure;
  11.         SPI_InitTypeDef  SPI_InitStructure;

  12.         RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE );        //PORTB时钟使能
  13.         RCC_APB1PeriphClockCmd(        RCC_APB1Periph_SPI2,  ENABLE );                                                                                                //SPI2时钟使能         

  14.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  15.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                                                                                                                          //PB13/14/15复用推挽输出
  16.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  17.         GPIO_Init(GPIOB, &GPIO_InitStructure);                                                                                                                                                                //初始化GPIOB
  18.         GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);                                                                                  //PB13/14/15上拉
  19.         
  20.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                                                                                                                                                        //PB0 RC522_CS
  21.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                                                                                                                  //PB0推挽输出
  22.         GPIO_Init(GPIOB, &GPIO_InitStructure);                                                                                                                                                                //初始化GPIOB
  23.         GPIO_SetBits(GPIOB,GPIO_Pin_0);                                                                                                                                                                                          //PB0上拉        

  24.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;                                                                                                                                                        //PC4 RC522_RST
  25.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                                                                                                                  //推挽输出
  26.         GPIO_Init(GPIOC, &GPIO_InitStructure);                                                                                                                                                                //初始化GPIOC
  27.         GPIO_SetBits(GPIOC,GPIO_Pin_4);                                                                                                                                                                                          //PC4

  28.         SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;                                          //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
  29.         SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                                                                                                                                        //设置SPI工作模式:设置为主SPI
  30.         SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                                                                                                                        //设置SPI的数据大小:SPI发送接收8位帧结构
  31.         SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                                                                                                                                                //串行同步时钟的空闲状态为高电平
  32. //                 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;        
  33. //                SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                                                                                                                                        //串行同步时钟的第一个跳变沿(下降)数据被采样
  34.         SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                                                                                                                                                //串行同步时钟的第二个跳变沿(上升)数据被采样
  35.         SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                                                                                                                                                        //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
  36. //RC522 SPI通讯时钟周期最小为100ns        即频率最大为10MHZ
  37. //RC522 数据在下降沿变化
  38.         SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;                                        //定义波特率预分频的值:波特率预分频值为256、传输速率36M/256=140.625KHz
  39.         SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                                                                                                                //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
  40.         SPI_InitStructure.SPI_CRCPolynomial = 7;                                                                                                                                                        //CRC值计算的多项式
  41.         SPI_Init(SPI2, &SPI_InitStructure);                                                                                                                                                                          //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

  42.         SPI_Cmd(SPI2, ENABLE); //使能SPI外设
  43.         RC522_CS=0;
  44.         SPI2_ReadWriteByte(0xaa);//启动传输        
  45.         RC522_CS=1;
  46.                
  47.   delay_ms(50);
  48.         PcdReset();//复位RC522读卡器
  49.         delay_ms(10);
  50.         PcdReset();//复位RC522读卡器
  51.         delay_ms(10);
  52.         PcdAntennaOff();//关闭天线发射                                                         
  53.         delay_ms(10);         
  54.   PcdAntennaOn();//开启天线发射
  55.         printf("RFID-MFRC522 TEST\r\nFindCard Starting ...\r\n");  //测试引脚初始化完成
  56. }


  57. void delay_ns(u32 ns)
  58. {
  59.   u32 i;
  60.   for(i=0;i<ns;i++)
  61.   {
  62.     __nop();
  63.     __nop();
  64.     __nop();
  65.   }
  66. }

  67. /***************************************************************************
  68.     - 功能描述:STM32f103 SPI读写字节函数
  69.     - 隶属模块:STM32 SPI操作
  70.   - 函数属性:外部,使用户使用
  71.   - 参数说明:TxData:要写入的字节
  72.   - 返回说明:读取到的字节
  73. - 函数说明:由于主机SPI通信时,在发送和接受时是同时进行的,即发送完了一个字节的数据后,也应当接受到一个字节的数据
  74.    (1)stm32先等待已发送的数据是否发送完成,如果没有发送完成,并且进入循环200次,则表示发送错误,返回收到的值为0;
  75.    (2)如果发送完成,stm32从SPI1总线发送TxData
  76.    (3)stm32再等待接收的数据是否接收完成,如果没有接收完成,并且进入循环200次,则表示接收错误,则返回值0
  77.    (4)如果接收完成了,则返回STm32读取的最新的数据  
  78.    
  79.    stm32
  80.    ------->等待已发送的数据是否完成
  81.    OK
  82.    ------->  
  83.    stm32发送数据
  84.    ------->等待待接收的数据是否完成
  85.    OK
  86.    ------->
  87.    stm32读取数据

  88. //SPIx 读写一个字节
  89. //TxData:要写入的字节
  90. //返回值:读取到的字节
  91. ***************************************************************************/

  92. char SPI2_ReadWriteByte(u8 TxData)
  93. {                                                
  94.         while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
  95.                 {
  96.                         ;
  97.                 }                          
  98.         SPI_I2S_SendData(SPI2, TxData);                                                                                                                                 //通过外设SPIx发送一个数据
  99.         while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
  100.                 {
  101. //                 retry++;
  102. //                 if(retry>200)return 0;
  103.                         ;
  104.                 }                                                              
  105.         return SPI_I2S_ReceiveData(SPI2);                                                                                                                         //返回通过SPIx最近接收的数据                                            
  106. }
  107. // u8 SPI2_ReadWriteByte(u8 Byte)
  108. // {
  109. //         while((SPI2->SR&0X02)==0);                //等待发送区空         
  110. //         SPI2->DR=Byte;                             //发送一个byte   
  111. //         while((SPI2->SR&0X01)==0);      //等待接收完一个byte  
  112. //         return SPI2->DR;                      //返回收到的数据                        
  113. // }


  114. //******************************************************************/
  115. //功    能:读RC522寄存器
  116. //参数说明:Address[IN]:寄存器地址
  117. //返    回:读出的值
  118. //******************************************************************/
  119. unsigned char ReadRawRC(unsigned char Address)
  120. {
  121.         u8 ucAddr;
  122.   u8 ucResult=0;
  123.         RC522_CS=0;
  124.         delay_us(10);
  125.    ucAddr = ((Address<<1)&0x7E)|0x80;
  126.         SPI2_ReadWriteByte(ucAddr);
  127.         delay_us(10);
  128.         ucResult=SPI2_ReadWriteByte(0);
  129.         delay_us(10);
  130.         RC522_CS=1;
  131.   return ucResult;
  132. }

  133. //******************************************************************/
  134. //功    能:写RC522寄存器
  135. //参数说明:Address[IN]:寄存器地址
  136. //          value[IN]:写入的值
  137. //******************************************************************/
  138. void WriteRawRC(unsigned char Address, unsigned char value)
  139. {
  140.         u8 ucAddr;
  141.         RC522_CS=0;
  142.         delay_us(10);
  143.         ucAddr = ((Address<<1)&0x7E) ;
  144.         SPI2_ReadWriteByte(ucAddr);
  145.         delay_us(10);
  146.         SPI2_ReadWriteByte(value);
  147.         delay_us(10);
  148.         RC522_CS=1;
  149. }

  150. //******************************************************************/
  151. //功    能:置RC522寄存器位
  152. //参数说明:reg[IN]:寄存器地址
  153. //          mask[IN]:置位值
  154. //******************************************************************/
  155. void SetBitMask(unsigned char reg,unsigned char mask)  
  156. {
  157.   char tmp = 0x0            ;
  158.   tmp = ReadRawRC(reg)| mask;
  159.   WriteRawRC(reg,tmp | mask);  // set bit mask
  160. }

  161. //******************************************************************/
  162. //功    能:清RC522寄存器位
  163. //参数说明:reg[IN]:寄存器地址
  164. //          mask[IN]:清位值
  165. //******************************************************************/
  166. void ClearBitMask(unsigned char reg,unsigned char mask)  
  167. {
  168.   char tmp = 0x0              ;
  169.   tmp = ReadRawRC(reg)&(~mask);
  170.   WriteRawRC(reg, tmp)        ;  // clear bit mask
  171. }

  172. //******************************************************************/
  173. //功    能:复位RC522
  174. //返    回: 成功返回MI_OK
  175. //******************************************************************/
  176. char PcdReset()
  177. {
  178.   RC522_RST=1;                             ;
  179.   delay_ns(10)                             ;
  180.   RC522_RST=0;                             ;
  181.   delay_ns(100)                             ;
  182.   RC522_RST=1;                             ;
  183.   delay_ns(10)                           ;
  184.   WriteRawRC(CommandReg,PCD_RESETPHASE);
  185.   delay_ns(100)                             ;
  186.   WriteRawRC(ModeReg,0x3D)             ;//定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363
  187.   WriteRawRC(TReloadRegL,30)           ;//16位定时器低位 30
  188.   WriteRawRC(TReloadRegH,0)            ;//16位定时器高位
  189.   WriteRawRC(TModeReg,0x8D)            ;//定义内部定时器的设置
  190.   WriteRawRC(TPrescalerReg,0x3E)       ;//设置定时器分频系数  
  191.   WriteRawRC(TxASKReg,0x40)            ;//调制发送信号为100%ASK
  192.   return MI_OK                         ;
  193. }
  194. //////////////////////////////////////////////////////////////////////
  195. //设置RC522的工作方式   
  196. //////////////////////////////////////////////////////////////////////
  197. char MF522PcdConfigISOType(unsigned char  type)
  198. {
  199.         if (type == 'A')        //ISO14443_A
  200.                 {
  201.                         ClearBitMask(Status2Reg,0x08);        //状态2寄存器         
  202.                         WriteRawRC(ModeReg,0x3D);        //3F  //和Mifare卡通讯,CRC初始值0x6363         
  203.                         WriteRawRC(RxSelReg,0x86);        //84   选择内部接收器设置,内部模拟部分调制信号,发送数据后,延迟6个位时钟,接收         
  204.                         WriteRawRC(RFCfgReg,0x7F);        //4F  配置接收器  48dB最大增益         
  205.                         WriteRawRC(TReloadRegL,30);        //tmoLength);TReloadVal = 'h6a =tmoLength(dec)      
  206.                         WriteRawRC(TReloadRegH,0);        //实际值是OXD3E 这部分主要是设置定时器寄存器      
  207.                         WriteRawRC(TModeReg,0x8D);
  208.                         WriteRawRC(TPrescalerReg,0x3E);
  209.                         delay_ns(1000);
  210.                         PcdAntennaOn();
  211.                 }     
  212.         else {return 0xFE;}  
  213.         return MI_OK;
  214. }  

  215. //******************************************************************/
  216. //开启天线发射  
  217. //每次启动或关闭天险发射之间应至少有1ms的间隔
  218. //******************************************************************/
  219. void PcdAntennaOn()
  220. {
  221.   unsigned char i;
  222.   WriteRawRC(TxASKReg,0x40)       ;
  223.   delay_us(10)                       ;
  224.   i = ReadRawRC(TxControlReg)     ;
  225.   if(!(i&0x03))
  226.     SetBitMask(TxControlReg, 0x03);
  227.   i=ReadRawRC(TxASKReg)       ;
  228. }


  229. //******************************************************************/
  230. //关闭天线发射
  231. //******************************************************************/
  232. void PcdAntennaOff()
  233. {
  234.   ClearBitMask(TxControlReg, 0x03);
  235. }

  236. //******************************************************************/
  237. //功    能:通过RC522和ISO14443卡通讯
  238. //参数说明:Command[IN]:RC522命令字
  239. //          pInData[IN]:通过RC522发送到卡片的数据
  240. //          InLenByte[IN]:发送数据的字节长度
  241. //          pOutData[OUT]:接收到的卡片返回数据
  242. //          *pOutLenBit[OUT]:返回数据的位长度
  243. //******************************************************************/
  244. char PcdComMF522(unsigned char Command  ,unsigned char *pInData ,
  245.                  unsigned char InLenByte,unsigned char *pOutData,
  246.                  unsigned int  *pOutLenBit                       )
  247. {
  248.   char status = MI_ERR                          ;
  249.   unsigned char irqEn   = 0x00                  ;
  250.   unsigned char waitFor = 0x00                  ;
  251.   unsigned char lastBits                        ;
  252.   unsigned char n                               ;
  253.   unsigned int  i                               ;
  254.   switch (Command)
  255.   {
  256.     case PCD_AUTHENT:
  257.       irqEn   = 0x12                            ;
  258.       waitFor = 0x10                            ;
  259.       break                                     ;
  260.     case PCD_TRANSCEIVE:
  261.       irqEn   = 0x77                            ;
  262.       waitFor = 0x30                            ;
  263.       break                                     ;
  264.     default:
  265.       break                                     ;
  266.   }
  267.   WriteRawRC(ComIEnReg,irqEn|0x80)              ; //
  268.   ClearBitMask(ComIrqReg,0x80)                  ;
  269.   WriteRawRC(CommandReg,PCD_IDLE)               ;
  270.   SetBitMask(FIFOLevelReg,0x80)                 ; // 清空FIFO
  271.   for(i=0; i<InLenByte; i++)
  272.     WriteRawRC(FIFODataReg,pInData[i])          ; // 数据写入FIFO
  273.   WriteRawRC(CommandReg, Command)               ; // 命令写入命令寄存器
  274.   if(Command == PCD_TRANSCEIVE)
  275.     SetBitMask(BitFramingReg,0x80)              ; // 开始发送     
  276.   i = 6000                                      ; //根据时钟频率调整,操作M1卡最大等待时间25ms
  277.   do
  278.   {
  279.     n = ReadRawRC(ComIrqReg)                    ;
  280.     i--                                         ;
  281.   }
  282.   while((i!=0)&&!(n&0x01)&&!(n&waitFor))        ;
  283.   ClearBitMask(BitFramingReg,0x80)              ;
  284.   if(i!=0)
  285.   {
  286.     if(!(ReadRawRC(ErrorReg)&0x1B))
  287.     {
  288.       status = MI_OK                            ;
  289.       if (n&irqEn&0x01)
  290.         status = MI_NOTAGERR                    ;
  291.       if(Command==PCD_TRANSCEIVE)
  292.       {
  293.         n = ReadRawRC(FIFOLevelReg)             ;
  294.         lastBits = ReadRawRC(ControlReg)&0x07   ;
  295.         if(lastBits)
  296.           *pOutLenBit = (n-1)*8 + lastBits      ;
  297.         else
  298.           *pOutLenBit = n*8                     ;
  299.         if(n==0)
  300.           n = 1                                 ;
  301.         if(n>MAXRLEN)
  302.           n = MAXRLEN                           ;
  303.         for (i=0; i<n; i++)
  304.           pOutData[i] = ReadRawRC(FIFODataReg)  ;
  305.       }
  306.     }
  307.     else
  308.       status = MI_ERR                           ;        
  309.   }
  310.   SetBitMask(ControlReg,0x80)                   ;// stop timer now
  311.   WriteRawRC(CommandReg,PCD_IDLE)               ;
  312.   return status;
  313. }

  314. //******************************************************************/
  315. //功    能:寻卡                                                    /
  316. //参数说明: req_code[IN]:寻卡方式                                   /
  317. //                0x52 = 寻感应区内所有符合14443A标准的卡           /
  318. //                0x26 = 寻未进入休眠状态的卡                       /
  319. //                pTagType[OUT]:卡片类型代码                       /
  320. //                0x4400 = Mifare_UltraLight                        /
  321. //                0x0400 = Mifare_One(S50)                          /
  322. //                0x0200 = Mifare_One(S70)                          /
  323. //                0x0800 = Mifare_Pro(X)                            /
  324. //                0x4403 = Mifare_DESFire                           /
  325. //返    回: 成功返回MI_OK                                           /
  326. //******************************************************************/
  327. char PcdRequest(unsigned char req_code,unsigned char *pTagType)
  328. {
  329.   char status                                        ;  
  330.   unsigned int  unLen                                ;
  331.   unsigned char ucComMF522Buf[MAXRLEN]               ;

  332.   ClearBitMask(Status2Reg,0x08)                      ;//清除MRCrypto1on,要用软件清零
  333.   WriteRawRC(BitFramingReg,0x07)                     ;//startsend=0,rxalign=0,在FIFO中存放的位置,TXlastbit=7
  334.   SetBitMask(TxControlReg,0x03)                      ;//TX2rfen=1,TX1RFen=1,传递调制的13.56MHZ的载波信号

  335.   ucComMF522Buf[0] = req_code                        ;

  336.   status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen       );
  337.   if ((status == MI_OK) && (unLen == 0x10))
  338.   {   
  339.     *pTagType     = ucComMF522Buf[0]                 ;
  340.     *(pTagType+1) = ucComMF522Buf[1]                 ;
  341.   }
  342.   else
  343.     status = MI_ERR                                  ;
  344.   return status                                      ;
  345. }

  346. //******************************************************************/
  347. //功    能:防冲撞                                                  /
  348. //参数说明: pSnr[OUT]:卡片序列号,4字节                             /
  349. //返    回: 成功返回MI_OK                                           /
  350. //******************************************************************/
  351. char PcdAnticoll(unsigned char *pSnr)
  352. {
  353.     char status;
  354.     unsigned char i,snr_check=0;
  355.     unsigned int  unLen;
  356.     unsigned char ucComMF522Buf[MAXRLEN];
  357.    
  358.     ClearBitMask(Status2Reg,0x08);//清除MRCrypto1on,要用软件清零
  359.     WriteRawRC(BitFramingReg,0x00);//表示最后一个字节所有位都发送
  360.     ClearBitMask(CollReg,0x80);//CollRegCollReg0冲突结束后冲突位被置零

  361.     ucComMF522Buf[0] = PICC_ANTICOLL1;
  362.     ucComMF522Buf[1] = 0x20;

  363.     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);

  364.     if (status == MI_OK)
  365.     {
  366.              for (i=0; i<4; i++)
  367.          {   
  368.              *(pSnr+i)  = ucComMF522Buf[i];
  369.              snr_check ^= ucComMF522Buf[i];
  370.          }
  371.          if (snr_check != ucComMF522Buf[i])
  372.          {   status = MI_ERR;    }
  373.     }
  374.    
  375.     SetBitMask(CollReg,0x80);//CollRegCollReg 在106kbps良好的防冲突情况下该位置1
  376.     return status;
  377. }

  378. /////////////////////////////////////////////////////////////////////
  379. //功    能:选定卡片
  380. //参数说明: pSnr[IN]:卡片序列号,4字节
  381. //返    回: 成功返回MI_OK
  382. /////////////////////////////////////////////////////////////////////
  383. char PcdSelect(unsigned char *pSnr)
  384. {
  385.     char status;
  386.     unsigned char i;
  387.     unsigned int  unLen;
  388.     unsigned char ucComMF522Buf[MAXRLEN];
  389.    
  390.     ucComMF522Buf[0] = PICC_ANTICOLL1;
  391.     ucComMF522Buf[1] = 0x70;
  392.     ucComMF522Buf[6] = 0;
  393.     for (i=0; i<4; i++)
  394.     {
  395.             ucComMF522Buf[i+2] = *(pSnr+i);
  396.             ucComMF522Buf[6]  ^= *(pSnr+i);
  397.     }
  398.     CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
  399.   
  400.     ClearBitMask(Status2Reg,0x08);//清零MFcryon

  401.     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
  402.    
  403.     if ((status == MI_OK) && (unLen == 0x18))
  404.     {   status = MI_OK;  }
  405.     else
  406.     {   status = MI_ERR;    }

  407.     return status;
  408. }

  409. //******************************************************************/
  410. //功    能:验证卡片密码
  411. //参数说明: auth_mode[IN]: 密码验证模式
  412. //                 0x60 = 验证A密钥
  413. //                 0x61 = 验证B密钥
  414. //          addr[IN]:块地址
  415. //          pKey[IN]:密码
  416. //          pSnr[IN]:卡片序列号,4字节
  417. //返    回: 成功返回MI_OK
  418. //******************************************************************/
  419. char PcdAuthState(unsigned char auth_mode,unsigned char addr,
  420.                   unsigned char *pKey,unsigned char *pSnr    )
  421. {
  422.     char status;
  423.     unsigned int  unLen;
  424.     unsigned char i,ucComMF522Buf[MAXRLEN];

  425.     ucComMF522Buf[0] = auth_mode;//验证A密钥
  426.     ucComMF522Buf[1] = addr;//addr[IN]:块地址
  427.     for (i=0; i<6; i++)
  428.     {    ucComMF522Buf[i+2] = *(pKey+i);   }
  429.     for (i=0; i<6; i++)
  430.     {    ucComMF522Buf[i+8] = *(pSnr+i);   }
  431.    
  432.     status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
  433.     if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
  434.     {   status = MI_ERR;   }
  435.    
  436.     return status;
  437. }

  438. //******************************************************************/
  439. //功    能:读取M1卡一块数据
  440. //参数说明: addr[IN]:块地址
  441. //          pData[OUT]:读出的数据,16字节
  442. //返    回: 成功返回MI_OK
  443. //******************************************************************/
  444. char PcdRead(unsigned char addr,unsigned char *pData)
  445. {
  446.     char status                                          ;
  447.     unsigned int  unLen                                  ;
  448.     unsigned char i,ucComMF522Buf[MAXRLEN]               ;

  449.     ucComMF522Buf[0] = PICC_READ                         ;
  450.     ucComMF522Buf[1] = addr                              ;
  451.     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2])       ;   
  452.     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,
  453.                          ucComMF522Buf,&unLen           );
  454.     if ((status == MI_OK) && (unLen == 0x90))
  455.     {
  456.         for (i=0; i<16; i++)
  457.             *(pData+i) = ucComMF522Buf[i];   
  458.     }
  459.     else
  460.       status = MI_ERR;      
  461.     return status;
  462. }

  463. //******************************************************************/
  464. //功    能:读取M1卡一块数据
  465. //参数说明: addr[IN]:块地址
  466. //          pData[OUT]:读出的数据,16字节
  467. //返    回: 成功返回MI_OK
  468. //******************************************************************/
  469. char Read_Block(unsigned char Block,unsigned char *Buf)
  470. {
  471.   char result                                             ;
  472.   result = PcdAuthState(0x60,Block,Password_Buffer,UID)   ;
  473.   if(result!=MI_OK)
  474.     return result                                         ;
  475.   result = PcdRead(Block,Buf)                             ;
  476. //  return result; // 2011.01.03
  477.   
  478.   if(result!=MI_OK)     return   result                   ;
  479.   if(Block!=0x00&&des_on)
  480.   {
  481. //     Des_Decrypt((char *)Buf    ,KK,(char *)Buf    )       ;
  482. //     Des_Decrypt((char *)&Buf[8],KK,(char *)&Buf[8])       ;  
  483.   }
  484.   return SUCCESS                                          ;
  485. }

  486. //******************************************************************/
  487. //功    能:写数据到M1卡一块
  488. //参数说明: addr[IN]:块地址
  489. //          pData[IN]:写入的数据,16字节
  490. //返    回: 成功返回MI_OK
  491. //******************************************************************/
  492. char PcdWrite(unsigned char addr,unsigned char *pData)
  493. {
  494.   char status                                             ;
  495.   unsigned int  unLen                                     ;
  496.   unsigned char i,ucComMF522Buf[MAXRLEN]                  ;
  497.    
  498.   ucComMF522Buf[0] = PICC_WRITE                           ;
  499.   ucComMF522Buf[1] = addr                                 ;
  500.   CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2])          ;
  501.   status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,
  502.                        ucComMF522Buf,&unLen          )    ;
  503.   if(  ( status != MI_OK)||(unLen != 4)
  504.      ||((ucComMF522Buf[0]&0x0F)!= 0x0A))
  505.     status = MI_ERR                                       ;           
  506.   if (status == MI_OK)
  507.   {
  508.     for (i=0; i<16; i++)
  509.       ucComMF522Buf[i] = *(pData+i)                       ;  
  510.     CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16])      ;
  511.     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,
  512.                          18,ucComMF522Buf,&unLen     )    ;
  513.     if(  (status != MI_OK)||(unLen != 4 )
  514.        ||((ucComMF522Buf[0]&0x0F)!= 0x0A))
  515.       status = MI_ERR                                     ;   
  516.   }   
  517.   return status                                           ;
  518. }
  519. //******************************************************************/
  520. //功    能:写数据到M1卡一块
  521. //参数说明: addr[IN]:块地址
  522. //          pData[IN]:写入的数据,16字节
  523. //返    回: 成功返回MI_OK
  524. //******************************************************************/

  525. //******************************************************************/
  526. //用MF522计算CRC16函数
  527. //******************************************************************/
  528. void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData)
  529. {
  530.     unsigned char i,n;
  531.     ClearBitMask(DivIrqReg,0x04);
  532.     WriteRawRC(CommandReg,PCD_IDLE);//取消当前命令
  533.     SetBitMask(FIFOLevelReg,0x80);//FlushBuffer 清除ErrReg 的标志位
  534.     for (i=0; i<len; i++)
  535.     {   WriteRawRC(FIFODataReg, *(pIndata+i));   }
  536.     WriteRawRC(CommandReg, PCD_CALCCRC);
  537.     i = 0xFF;
  538.     do
  539.     {
  540.         n = ReadRawRC(DivIrqReg);
  541.         i--;
  542.     }
  543.     while ((i!=0) && !(n&0x04));//当CRCIRq所有数据被处理完毕该位置位
  544.     pOutData[0] = ReadRawRC(CRCResultRegL);//显示计算出来的CRC值
  545.     pOutData[1] = ReadRawRC(CRCResultRegM);
  546. }


  547. //==============================================================================
  548. //读取卡的类型
  549. //读取卡的ID号
  550. // 卡片:12AAD52D
  551. // 卡环:EC838322
  552. //==============================================================================
  553. void ReaderCard(void)
  554. {
  555.         char temp_value;
  556.         if(PcdRequest(PICC_REQALL,Temp)==MI_OK)        //选卡
  557.         {
  558.                 if(Temp[0]==0x04&&Temp[1]==0x00)  
  559.                                 printf("MFOne-S50");
  560.                 else if(Temp[0]==0x02&&Temp[1]==0x00)
  561.                         printf("MFOne-S70");
  562.                 else if(Temp[0]==0x44&&Temp[1]==0x00)
  563.                         printf("MF-UltraLight");
  564.                 else if(Temp[0]==0x08&&Temp[1]==0x00)
  565.                         printf("MF-Pro");
  566.                 else if(Temp[0]==0x44&&Temp[1]==0x03)
  567.                         printf("MF Desire");
  568.                 else
  569.                         printf("Unknown");
  570.                 if(PcdAnticoll(UID)==MI_OK)                        //防冲撞
  571.                 {
  572.                         printf("Card Id is:");
  573.                         /* 获取卡值  */
  574.                         Uart1_SendHexDisplay(UID[0]);
  575.                         Uart1_SendHexDisplay(UID[1]);
  576.                         Uart1_SendHexDisplay(UID[2]);
  577.                         Uart1_SendHexDisplay(UID[3]);
  578.                         printf("\r\n");                //发送换行指令
  579.                         temp_value = ((UID[0]>>4)*10+(UID[0]&0x0f));
  580.                         printf("管理员:%d\r\n",temp_value);
  581. //                        switch(temp_value)
  582. //                        {
  583. //                                case 12 : printf("管理员:%d\r\n",temp_value);    break;
  584. //                                case 152: printf("学生  :%d\r\n",temp_value);    break;
  585. //                                default : printf("无效卡:%d\r\n",temp_value);    break;
  586. //                        }                                    
  587.                 }
  588.   }
  589. }
复制代码
全部程序51hei下载地址:
RFID_RC522.7z (195.99 KB, 下载次数: 394)

评分

参与人数 2黑币 +65 收起 理由
杀死比亚 + 15 很给力!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:218113 发表于 2021-1-27 14:54 | 显示全部楼层
感谢老铁,资料非常好。谢谢了
回复

使用道具 举报

ID:210139 发表于 2021-2-7 10:59 | 显示全部楼层
很不错,在网上很少有直接移植,就能成功程序,楼主的很不错,烧录好以后就能直接用
回复

使用道具 举报

ID:884825 发表于 2021-2-19 10:10 | 显示全部楼层
太感谢了,驱动移植很方便
回复

使用道具 举报

ID:890184 发表于 2021-4-27 01:22 | 显示全部楼层
楼主您好,我怎么找不到Uart1_SendHexDisplay这个函数的定义。您能告诉我吗?
回复

使用道具 举报

ID:933937 发表于 2022-3-24 15:09 | 显示全部楼层
我想知道实物实现需要买什么硬件,或者说识别模块
回复

使用道具 举报

ID:528966 发表于 2022-10-18 13:49 | 显示全部楼层
楼主的很不错,烧录好以后就能直接用
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表