找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5095|回复: 0
打印 上一主题 下一主题
收起左侧

51单片机MFRC522程序注释

[复制链接]
跳转到指定楼层
楼主
ID:424242 发表于 2018-11-10 20:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
单片机源程序如下(带有详细的代码注释):
  1. #include <intrins.h>
  2. #include "reg52.h"
  3. #include "main.h"
  4. #include "mfrc522.h"
  5. #include <string.h>
  6. #define MAXRLEN 18      

  7. /******* RxModeReg默认为106kbit/s的通信速率 ******************/
  8.                  
  9. /***********************************************************************
  10. * 功    能:寻卡
  11. * 参数说明: req_code[IN]:寻卡方式
  12. *                 0x52 = 寻感应区内所有符合14443A标准的卡
  13. *                 0x26 = 寻未进入休眠状态的卡
  14. *           pTagType[OUT]:卡片类型代码
  15. *                 0x4400 = Mifare_UltraLight
  16. *                 0x0400 = Mifare_One(S50)
  17. *                 0x0200 = Mifare_One(S70)
  18. *                 0x0800 = Mifare_Pro(X)
  19. *                 0x4403 = Mifare_DESFire
  20. * 返    回: 成功返回MI_OK
  21. ***********************************************************************/
  22. char PcdRequest(unsigned char req_code,unsigned char *pTagType)
  23. {
  24.    char status;  
  25.    unsigned int  unLen;
  26.    unsigned char ucComMF522Buf[MAXRLEN];
  27. //  unsigned char xTest ;
  28.    ClearBitMask(Status2Reg,0x08);  // 清MFCrypto1On,只能通过软件清零,该位用来指示Crypto1的接通情况,MFAuthent(验证密钥)命令成功执行后置1
  29.    WriteRawRC(BitFramingReg,0x07); // TxLastBits([2-0])表示发送的最后一个字节7位发送

  30. //  xTest = ReadRawRC(BitFramingReg);
  31. //  if(xTest == 0x07 )
  32. //   { LED_GREEN  =0 ;}
  33. // else {LED_GREEN =1 ;while(1){}}
  34.    SetBitMask(TxControlReg,0x03); // TxControlReg低2位(Tx2RFEn和Tx1RFEn)置1,Tx2和Tx1管脚输出信号调制在13.56MHz的载波上

  35.    ucComMF522Buf[0] = req_code;

  36.    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);  // PCD_TRANSCEIVE == 0x0c发送并接收数据
  37. //     if(status  == MI_OK )
  38. //   { LED_GREEN  =0 ;}
  39. //   else {LED_GREEN =1 ;}
  40.    if ((status == MI_OK) && (unLen == 0x10))   // 发送成功并且接收16位数据
  41.    {   
  42.        *pTagType     = ucComMF522Buf[0];
  43.        *(pTagType+1) = ucComMF522Buf[1];  // 接收的卡片类型保存在pTagType中
  44.    }
  45.    else
  46.    {   status = MI_ERR;   }
  47.    
  48.    return status;
  49. }

  50. /**********************************************************************
  51. * 功    能:防冲撞
  52. * 参数说明: pSnr[OUT]:卡片序列号,4字节
  53. * 返    回: 成功返回MI_OK
  54. **********************************************************************/  
  55. char PcdAnticoll(unsigned char *pSnr)
  56. {
  57.     char status;
  58.     unsigned char i,snr_check=0;
  59.     unsigned int  unLen;
  60.     unsigned char ucComMF522Buf[MAXRLEN];
  61.    

  62.     ClearBitMask(Status2Reg,0x08);   // 清MFCrypto1On,只能通过软件清零,该位用来指示Crypto1的接通情况,MFAuthent(验证密钥)命令成功执行后置1
  63.     WriteRawRC(BitFramingReg,0x00);  // TxLastBits([2-0])表示发送的最后一个字节的所有位都发送
  64.     ClearBitMask(CollReg,0x80);      // 高位置0,所有接收的位在冲突后清除

  65.     ucComMF522Buf[0] = PICC_ANTICOLL1; // 防冲撞(0x93)
  66.     ucComMF522Buf[1] = 0x20;

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

  68.     if (status == MI_OK)
  69.     {
  70.              for (i=0; i<4; i++)
  71.          {   
  72.              *(pSnr+i)  = ucComMF522Buf[i];  // 读取卡片序列号
  73.              snr_check ^= ucComMF522Buf[i];
  74.          }
  75.          if (snr_check != ucComMF522Buf[i])
  76.          {   status = MI_ERR;    }
  77.     }
  78.    
  79.     SetBitMask(CollReg,0x80);  // 置1,回归正常
  80.     return status;
  81. }

  82. /**********************************************************************
  83. * 功    能:选定卡片
  84. * 参数说明: pSnr[IN]:卡片序列号,4字节
  85. * 返    回: 成功返回MI_OK
  86. **********************************************************************/
  87. char PcdSelect(unsigned char *pSnr)
  88. {
  89.     char status;
  90.     unsigned char i;
  91.     unsigned int  unLen;
  92.     unsigned char ucComMF522Buf[MAXRLEN];
  93.    
  94.     ucComMF522Buf[0] = PICC_ANTICOLL1;  // 防冲撞
  95.     ucComMF522Buf[1] = 0x70;
  96.     ucComMF522Buf[6] = 0;
  97.     for (i=0; i<4; i++)
  98.     {
  99.             ucComMF522Buf[i+2] = *(pSnr+i);   // 将卡片序列号写进去
  100.             ucComMF522Buf[6]  ^= *(pSnr+i);
  101.     }
  102.     CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);  // CRC校验卡片序列号
  103.   
  104.     ClearBitMask(Status2Reg,0x08);  // 清MFCrypto1On,只能通过软件清零,该位用来指示Crypto1的接通情况,MFAuthent(验证密钥)命令成功执行后置1

  105.     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);  // 发送卡片的序列号及其校验码
  106.    
  107.     if ((status == MI_OK) && (unLen == 0x18))  // 接收24位
  108.     {   status = MI_OK;  }
  109.     else
  110.     {   status = MI_ERR;    }

  111.     return status;
  112. }

  113. /**********************************************************************
  114. * 功    能:验证卡片密码
  115. * 参数说明: auth_mode[IN]: 密码验证模式
  116. *                  0x60 = 验证A密钥
  117. *                  0x61 = 验证B密钥
  118. *           addr[IN]:块地址
  119. *           pKey[IN]:密码
  120. *           pSnr[IN]:卡片序列号,4字节
  121. * 返    回: 成功返回MI_OK
  122. **********************************************************************/               
  123. char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr)
  124. {
  125.     char status;
  126.     unsigned int  unLen;
  127.     unsigned char i,ucComMF522Buf[MAXRLEN];

  128.     ucComMF522Buf[0] = auth_mode;   // 验证模式
  129.     ucComMF522Buf[1] = addr;        // 块地址
  130.     for (i=0; i<6; i++)
  131.     {    ucComMF522Buf[i+2] = *(pKey+i);   }  // 密码
  132.     for (i=0; i<4; i++)                                          /*源代码是6,不知道正不正确*/
  133.     {    ucComMF522Buf[i+8] = *(pSnr+i);   }  // 防冲撞卡号
  134. //   memcpy(&ucComMF522Buf[2], pKey, 6);
  135. //   memcpy(&ucComMF522Buf[8], pSnr, 4);
  136.    
  137.     status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
  138.     if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
  139.     {   status = MI_ERR;   }
  140.    
  141.     return status;
  142. }

  143. /**********************************************************************
  144. * 功    能:读取M1卡一块数据
  145. * 参数说明: addr[IN]:块地址
  146. *           pData[OUT]:读出的数据,16字节
  147. * 返    回: 成功返回MI_OK
  148. ***********************************************************************/
  149. char PcdRead(unsigned char addr,unsigned char *pData)
  150. {
  151.     char status;
  152.     unsigned int  unLen;
  153.     unsigned char i,ucComMF522Buf[MAXRLEN];

  154.     ucComMF522Buf[0] = PICC_READ;  // 0x30,读块
  155.     ucComMF522Buf[1] = addr;
  156.     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);  // 计算CRC,存放在ucComMF522Buf[2]和ucComMF522Buf[3]中
  157.    
  158.     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);  // 将4个字节放松出去,并接收数据
  159.     if ((status == MI_OK) && (unLen == 0x90))  // 接收144位(18字节)
  160. //   {   memcpy(pData, ucComMF522Buf, 16);   }
  161.     {
  162.         for (i=0; i<16; i++)
  163.         {    *(pData+i) = ucComMF522Buf[i];   }  // 将前16字节读出
  164.     }
  165.     else
  166.     {   status = MI_ERR;   }
  167.    
  168.     return status;
  169. }

  170. /********************************************************************
  171. * 功    能:写数据到M1卡一块
  172. * 参数说明: addr[IN]:块地址
  173. *           pData[IN]:写入的数据,16字节
  174. * 返    回: 成功返回MI_OK
  175. ********************************************************************/                  
  176. char PcdWrite(unsigned char addr,unsigned char *pData)
  177. {
  178.     char status;
  179.     unsigned int  unLen;
  180.     unsigned char i,ucComMF522Buf[MAXRLEN];
  181.    
  182.     ucComMF522Buf[0] = PICC_WRITE;  // 0xa0 写块
  183.     ucComMF522Buf[1] = addr;
  184.     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);  // 计算CRC

  185.     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);  // 发送写命令和地址

  186.     if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) // 接收低四位为1010
  187.     {   status = MI_ERR;   }
  188.         
  189.     if (status == MI_OK)
  190.     {
  191.         //memcpy(ucComMF522Buf, pData, 16);
  192.         for (i=0; i<16; i++)
  193.         {    ucComMF522Buf[i] = *(pData+i);   }  // 16字节数据
  194.         CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]); // 两位CRC计算字节

  195.         status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);  // 发送18字节
  196.         if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) // 返回低四位为1010
  197.         {   status = MI_ERR;   }
  198.     }
  199.    
  200.     return status;
  201. }



  202. /*********************************************************************
  203. * 功    能:命令卡片进入休眠状态
  204. * 返    回: 成功返回MI_OK
  205. *********************************************************************/
  206. char PcdHalt(void)
  207. {
  208.     char status;
  209.     unsigned int  unLen;
  210.     unsigned char ucComMF522Buf[MAXRLEN];

  211.     ucComMF522Buf[0] = PICC_HALT;  // 0x50,休眠
  212.     ucComMF522Buf[1] = 0;
  213.     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); // 计算校验位

  214.     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); // 发送

  215.     return MI_OK;
  216. }

  217. /*********************************************************************
  218. * 用MF522计算CRC16函数
  219. *********************************************************************/
  220. void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData)
  221. {
  222.     unsigned char i,n;
  223.     ClearBitMask(DivIrqReg,0x04);    // CRCIRQ清零
  224.     WriteRawRC(CommandReg,PCD_IDLE); // 空闲命令
  225.     SetBitMask(FIFOLevelReg,0x80);   // FIFOLevelReg中FlushBuffer位置1,表示缓冲区读和写指针清除,即缓冲区无数据,用来存放一下批数据,ErrReg的BufferOvfl清楚
  226.     for (i=0; i<len; i++)
  227.     {   WriteRawRC(FIFODataReg, *(pIndata+i));   }  // 将数据写入缓冲区
  228.     WriteRawRC(CommandReg, PCD_CALCCRC);            // 启动CRC计算,结果存于CRCResultReg中
  229.     i = 0xFF;
  230.     do
  231.     {
  232.         n = ReadRawRC(DivIrqReg);
  233.         i--;
  234.     }
  235.     while ((i!=0) && !(n&0x04));        // CRCIRQ置位,当CRC有效且所有数据被处理则需要置1,退出循环,或者是执行了127次读取认为完成CRC也退出循环
  236.     pOutData[0] = ReadRawRC(CRCResultRegL);  
  237.     pOutData[1] = ReadRawRC(CRCResultRegM);  // 计算结果输出到pOutData中
  238. }

  239. /*********************************************************************
  240. * 功    能:复位RC522
  241. * 返    回: 成功返回MI_OK
  242. *********************************************************************/
  243. char PcdReset(void)
  244. {
  245.     MF522_RST=1;
  246.     _nop_();
  247.     MF522_RST=0;   // 复位
  248.     _nop_();
  249.     MF522_RST=1;
  250.      _nop_();
  251.     WriteRawRC(CommandReg,PCD_RESETPHASE); // 0x0F,软件复位
  252.     _nop_();
  253.    
  254.     WriteRawRC(ModeReg,0x3D);            // 和Mifare卡通讯,CRC初始值0x6363
  255.     WriteRawRC(TReloadRegL,30);          // 48
  256.     WriteRawRC(TReloadRegH,0);
  257.     WriteRawRC(TModeReg,0x8D);           // 10001101(141):发送完开始计时,接收时停止计时,自动重装
  258.     WriteRawRC(TPrescalerReg,0x3E);      // 00111110(62),3390  定时时间:3391*49/6.78=24.5ms
  259.     WriteRawRC(TxAutoReg,0x40);          // 控制驱动天线
  260.     return MI_OK;
  261. }
  262. /*********************************************************************
  263. * 设置RC632的工作方式
  264. *********************************************************************/
  265. char M500PcdConfigISOType(unsigned char type)
  266. {
  267.    if (type == 'A')                     //ISO14443_A
  268.    {
  269.        ClearBitMask(Status2Reg,0x08);

  270. /*     WriteRawRC(CommandReg,0x20);    //as default   
  271.        WriteRawRC(ComIEnReg,0x80);     //as default
  272.        WriteRawRC(DivlEnReg,0x0);      //as default
  273.            WriteRawRC(ComIrqReg,0x04);     //as default
  274.            WriteRawRC(DivIrqReg,0x0);      //as default
  275.            WriteRawRC(Status2Reg,0x0);//80    //trun off temperature sensor
  276.            WriteRawRC(WaterLevelReg,0x08); //as default
  277.        WriteRawRC(ControlReg,0x20);    //as default
  278.            WriteRawRC(CollReg,0x80);    //as default
  279. */
  280.        WriteRawRC(ModeReg,0x3D);//3F
  281. /*           WriteRawRC(TxModeReg,0x0);      //as default???
  282.            WriteRawRC(RxModeReg,0x0);      //as default???
  283.            WriteRawRC(TxControlReg,0x80);  //as default???

  284.            WriteRawRC(TxSelReg,0x10);      //as default???
  285.    */
  286.        WriteRawRC(RxSelReg,0x86);//84  // 内部模拟部分的调制信号作为非接触式UART输入,发送后接收器启动延时6个位时钟
  287. //      WriteRawRC(RxThresholdReg,0x84);//as default
  288. //      WriteRawRC(DemodReg,0x4D);      //as default

  289. //      WriteRawRC(ModWidthReg,0x13);//26
  290.        WriteRawRC(RFCfgReg,0x7F);   //4F  // 接收信号电压增益23dB
  291.         /*   WriteRawRC(GsNReg,0x88);        //as default???
  292.            WriteRawRC(CWGsCfgReg,0x20);    //as default???
  293.        WriteRawRC(ModGsCfgReg,0x20);   //as default???
  294. */
  295.               WriteRawRC(TReloadRegL,30);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec)
  296.            WriteRawRC(TReloadRegH,0);
  297.        WriteRawRC(TModeReg,0x8D);
  298.            WriteRawRC(TPrescalerReg,0x3E);
  299.            

  300.   //     PcdSetTmo(106);
  301.                                 delay(10);
  302.        PcdAntennaOn();
  303.    }
  304.    else{ return -1; }
  305.    
  306.    return MI_OK;
  307. }
  308. /********************************************************************
  309. * 功    能:读RC632寄存器     SPI方式
  310. * 参数说明:Address[IN]:寄存器地址
  311. * 返    回:读出的值
  312. *********************************************************************/
  313. unsigned char ReadRawRC(unsigned char Address)
  314. {
  315.      unsigned char i, ucAddr;
  316.      unsigned char ucResult=0;

  317.      MF522_SCK = 0;
  318.      MF522_NSS = 0;
  319.      ucAddr = ((Address<<1)&0x7E)|0x80;

  320.      for(i=8;i>0;i--)
  321.      {
  322.          MF522_SI = ((ucAddr&0x80)==0x80);
  323.          MF522_SCK = 1;
  324.          ucAddr <<= 1;
  325.          MF522_SCK = 0;
  326.      }

  327.      for(i=8;i>0;i--)
  328.      {
  329.          MF522_SCK = 1;
  330.          ucResult <<= 1;
  331.          ucResult|=(bit)MF522_SO;
  332.          MF522_SCK = 0;
  333.      }

  334.      MF522_NSS = 1;
  335.      MF522_SCK = 1;
  336.      return ucResult;
  337. }

  338. /*********************************************************************
  339. * 功    能:写RC632寄存器
  340. * 参数说明:Address[IN]:寄存器地址
  341. *           value[IN]:写入的值
  342. **********************************************************************/
  343. void WriteRawRC(unsigned char Address, unsigned char value)
  344. {  
  345.     unsigned char i, ucAddr;

  346.     MF522_SCK = 0;
  347.     MF522_NSS = 0;
  348.     ucAddr = ((Address<<1)&0x7E);  // 地址高位为0表示写,地位必须为0

  349.     for(i=8;i>0;i--)
  350.     {
  351.         MF522_SI = ((ucAddr&0x80)==0x80);
  352.         MF522_SCK = 1;
  353.         ucAddr <<= 1;
  354.         MF522_SCK = 0;
  355.     }

  356.     for(i=8;i>0;i--)
  357.     {
  358.         MF522_SI = ((value&0x80)==0x80);
  359.         MF522_SCK = 1;
  360.         value <<= 1;
  361.         MF522_SCK = 0;
  362.     }
  363.     MF522_NSS = 1;
  364.     MF522_SCK = 1;
  365. }

  366. /*********************************************************************
  367. * 功    能:置RC522寄存器位
  368. * 参数说明:reg[IN]:寄存器地址
  369. *           mask[IN]:置位值
  370. *********************************************************************/
  371. void SetBitMask(unsigned char reg,unsigned char mask)  
  372. {
  373.     char tmp = 0x0;
  374.     tmp = ReadRawRC(reg);
  375.     WriteRawRC(reg,tmp | mask);  // set bit mask
  376. }

  377. /*********************************************************************
  378. * 功    能:清RC522寄存器位
  379. * 参数说明:reg[IN]:寄存器地址
  380. *           mask[IN]:清位值
  381. *********************************************************************/
  382. void ClearBitMask(unsigned char reg,unsigned char mask)  
  383. {
  384.     char tmp = 0x0;
  385.     tmp = ReadRawRC(reg);
  386.     WriteRawRC(reg, tmp & ~mask);  // clear bit mask
  387. }

  388. /*********************************************************************
  389. * 功    能:通过RC522和ISO14443卡通讯
  390. * 参数说明:Command[IN]:RC522命令字
  391. *           pInData[IN]:通过RC522发送到卡片的数据
  392. *           InLenByte[IN]:发送数据的字节长度
  393. *           pOutData[OUT]:接收到的卡片返回数据
  394. *           *pOutLenBit[OUT]:返回数据的位长度
  395. *********************************************************************/
  396. char PcdComMF522(unsigned char Command,
  397.                  unsigned char *pInData,
  398.                  unsigned char InLenByte,
  399.                  unsigned char *pOutData,
  400.                  unsigned int  *pOutLenBit)
  401. {
  402.     char status = MI_ERR;
  403.     unsigned char irqEn   = 0x00;
  404.     unsigned char waitFor = 0x00;
  405.     unsigned char lastBits;
  406.     unsigned char n;
  407.     unsigned int i;
  408.     switch (Command)
  409.     {
  410.        case PCD_AUTHENT:      // 验证密钥
  411.           irqEn   = 0x12;
  412.           waitFor = 0x10;
  413.           break;
  414.        case PCD_TRANSCEIVE:   // 发送并接收数据
  415.           irqEn   = 0x77;
  416.           waitFor = 0x30;
  417.           break;
  418.        default:
  419.          break;
  420.     }
  421.    
  422.     WriteRawRC(ComIEnReg,irqEn|0x80); // ComIEnReg:中断请求的使能位。验证密钥:(10010010)位7:管脚IRQ与Status1Reg的IRq反相。位4:允许空闲中断请求(IdleIRq位)传递到IRQ管脚上。位1:允许错误中断请求(ErrIRq位)传递到IRQ管脚上。
  423.                                       //                             发送并接收数据:(11110111)除高位中断请求外,其他都能传到IRQ管脚上
  424.     ClearBitMask(ComIrqReg,0x80);     // ComIrqReg的屏蔽位清零
  425.     WriteRawRC(CommandReg,PCD_IDLE);  // CommandReg低4位写0000B,处于空闲模式
  426.     SetBitMask(FIFOLevelReg,0x80);    // FIFOLevelReg中FlushBuffer位置1,表示缓冲区读和写指针清除,即缓冲区无数据,用来存放一下批数据,ErrReg的BufferOvfl清除
  427.    
  428.     for (i=0; i<InLenByte; i++)
  429.     {   
  430.             WriteRawRC(FIFODataReg, pInData[i]);  // 将pInData数组的数据写进FIFO缓冲区
  431.     }
  432.     WriteRawRC(CommandReg, Command);    // 验证密钥 or 发送并接收数据
  433.    
  434.    
  435.     if (Command == PCD_TRANSCEIVE)
  436.     {    SetBitMask(BitFramingReg,0x80);  }  // 启动数据的发送
  437.    
  438. //    i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms
  439. i = 2000;
  440.     do
  441.     {
  442.          n = ReadRawRC(ComIrqReg);
  443.          i--;
  444.     }
  445.     while ((i!=0) && !(n&0x01) && !(n&waitFor));  //如果i不为0,并且定时器没减到0,并且没有未知命令和自身终止命令和接收器没有检测到有效数据流,就继续循环,退出循环则表示接收完成
  446.     ClearBitMask(BitFramingReg,0x80);    // StartSend位清零
  447.               
  448.     if (i!=0)
  449.     {   
  450.          if(!(ReadRawRC(ErrorReg)&0x1B))   // FIFO没有溢出、接收器启动并完成接收之后:(没冲突)、(CRC没出错)、(没有SOF错误)、(验证时接受字节数没错)
  451.          {
  452.              status = MI_OK;
  453.              if (n & irqEn & 0x01)           // 发送并接收数据、定时器减到0
  454.              {   status = MI_NOTAGERR;   }   // 没有找到目标错误
  455.              if (Command == PCD_TRANSCEIVE)
  456.              {
  457.                        n = ReadRawRC(FIFOLevelReg);  // 读FIFO保存的字节数
  458.                       lastBits = ReadRawRC(ControlReg) & 0x07;  // 最后一个接收的字节的有效位数(0则表示8位都有效)
  459.                 if (lastBits)
  460.                 {   *pOutLenBit = (n-1)*8 + lastBits;   }
  461.                 else
  462.                 {   *pOutLenBit = n*8;   }
  463.                 if (n == 0)
  464.                 {   n = 1;    }
  465.                 if (n > MAXRLEN)
  466.                 {   n = MAXRLEN;   }
  467.                 for (i=0; i<n; i++)
  468.                 {   pOutData[i] = ReadRawRC(FIFODataReg);    } // 将缓冲区的数据读出
  469.             }
  470.          }
  471.          else
  472.          {   status = MI_ERR;   }  // 验证错误
  473.         
  474.    }
  475.    

  476.    SetBitMask(ControlReg,0x80);           // stop timer now
  477.    WriteRawRC(CommandReg,PCD_IDLE);       // 空闲
  478.    return status;
  479. }


  480. /********************************************************************
  481. * 开启天线  
  482. * 每次启动或关闭天险发射之间应至少有1ms的间隔
  483. ********************************************************************/
  484. void PcdAntennaOn()
  485. {
  486.     unsigned char i;
  487.     i = ReadRawRC(TxControlReg);
  488.     if (!(i & 0x03))
  489.     {
  490.         SetBitMask(TxControlReg, 0x03);  // Tx1和Tx2管脚的输出信号调制到13.56MHz的载波上
  491.     }
  492. }


  493. /********************************************************************
  494. * 关闭天线
  495. ********************************************************************/
  496. void PcdAntennaOff()
  497. {
  498.     ClearBitMask(TxControlReg, 0x03);
  499. }


  500. /*********************************************************************
  501. * 功    能:扣款和充值
  502. * 参数说明: dd_mode[IN]:命令字
  503. *                0xC0 = 扣款
  504. *                0xC1 = 充值
  505. *           addr[IN]:钱包地址
  506. *           pValue[IN]:4字节增(减)值,低位在前
  507. * 返    回: 成功返回MI_OK
  508. *********************************************************************/                 
  509. char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue)
  510. {
  511.     char status;
  512.     unsigned int  unLen;
  513.     unsigned char ucComMF522Buf[MAXRLEN];
  514.    
  515.     ucComMF522Buf[0] = dd_mode;  // 充值还是扣款(加还是减)
  516.     ucComMF522Buf[1] = addr;     // 钱包地址(写卡的地址)
  517.     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); // 计算CRC

  518.     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);  // 发送数据并接收数据

  519.     if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))  // 卡片返回1010
  520.     {   status = MI_ERR;   }
  521.         
  522.     if (status == MI_OK)
  523.     {
  524.         //(ucComMF522Buf, pValue, 4);
  525.         for (i=0; i<4; i++)  //16
  526.         {    ucComMF522Buf[i] = *(pValue+i);   }
  527.         CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
  528.         unLen = 0;
  529.         status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);  // 发送充或者扣的数据
  530.         if (status != MI_ERR)
  531.         {    status = MI_OK;    }
  532.     }
  533.    
  534.     if (status == MI_OK)
  535.     {
  536.         ucComMF522Buf[0] = PICC_TRANSFER;  // 保存缓冲区中的数据
  537.         ucComMF522Buf[1] = addr;           // 地址
  538.         CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);   // 计算crc
  539.    
  540.         status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);  // 发送保存缓冲区数据的命令

  541.         if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))  // 卡片返回1010B
  542.         {   status = MI_ERR;   }
  543.     }
  544.     return status;
  545. }

  546. /**********************************************************************
  547. * 功    能:备份钱包
  548. * 参数说明: sourceaddr[IN]:源地址
  549. *           goaladdr[IN]:目标地址
  550. * 返    回: 成功返回MI_OK
  551. **********************************************************************/
  552. char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr)
  553. {
  554.     char status;
  555.     unsigned int  unLen;
  556.     unsigned char ucComMF522Buf[MAXRLEN];

  557.     ucComMF522Buf[0] = PICC_RESTORE;  // 0xC2,调块数据到缓冲区
  558.     ucComMF522Buf[1] = sourceaddr;    // 源地址
  559.     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);  // 计算CRC

  560.     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);  // 发送命令:将源地址的数据调到缓冲区

  561.     if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
  562.     {   status = MI_ERR;   }
  563.    
  564.     if (status == MI_OK)
  565.     {
  566.         ucComMF522Buf[0] = 0;
  567.         ucComMF522Buf[1] = 0;
  568.         ucComMF522Buf[2] = 0;
  569.         ucComMF522Buf[3] = 0;
  570.         CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);

  571.         status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
  572.         if (status != MI_ERR)
  573.         {    status = MI_OK;    }
  574.     }
  575.    
  576.     if (status != MI_OK)
  577.     {    return MI_ERR;   }
  578.    
  579.     ucComMF522Buf[0] = PICC_TRANSFER;   // 保存缓冲区内容命令
  580.     ucComMF522Buf[1] = goaladdr;        // 目标地址

  581.     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);

  582.     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);  // 发送命令:将缓冲区的内容发送到目标地址

  583.     if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
  584.     {   status = MI_ERR;   }

  585.     return status;
  586. }

  587. /*
  588. ///////////////////////////////////////////////////////////////////////
  589. // Delay 10ms
  590. ///////////////////////////////////////////////////////////////////////
  591. void delay_10ms(unsigned int _10ms)
  592. {
  593. #ifndef NO_TIMER2
  594.     RCAP2LH = RCAP2_10ms;
  595.     T2LH    = RCAP2_10ms;
  596.    
  597.     TR2 = TRUE;
  598.     while (_10ms--)
  599.     {
  600.             while (!TF2);
  601.             TF2 = FALSE;
  602.     }
  603.     TR2 = FALSE;
  604. #else
  605.     while (_10ms--)
  606.     {
  607.             delay_50us(19);
  608.             if (CmdValid)
  609.                 return;
  610.             delay_50us(20);
  611.             if (CmdValid)
  612.                 return;
  613.             delay_50us(20);
  614.             if (CmdValid)
  615.                 return;
  616.             delay_50us(20);
  617.             if (CmdValid)
  618.                 return;
  619.             delay_50us(20);
  620.             if (CmdValid )
  621.                 return;
  622.             delay_50us(20);
  623.             if (CmdValid)
  624.                 return;
  625.             delay_50us(20);
  626.             if (CmdValid)
  627.                 return;
  628.             delay_50us(20);
  629.             if (CmdValid)
  630.                 return;
  631.             delay_50us(20);
  632.             if (CmdValid)
  633.                 return;
  634.             delay_50us(19);
  635.             if (CmdValid)
  636.                 return;
  637.     }
  638. #endif
  639. }
  640. */
复制代码

所有资料51hei提供下载:
mfrc522程序注释.doc (23.44 KB, 下载次数: 57)
MFRC500中文资料.pdf (1.7 MB, 下载次数: 36)
51单片机RC522射频卡驱动.docx (21.9 KB, 下载次数: 53)

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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