找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2681|回复: 0
收起左侧

STM32驱动RC522代码分享

[复制链接]
ID:297748 发表于 2018-11-29 11:59 | 显示全部楼层 |阅读模式
这是野火的代码,自己改了以后,可以直插直用,有问题,评论区见

单片机源程序如下:
  1. #include "rc522_function.h"
  2. #include "rc522_config.h"
  3. #include "stm32f10x.h"
  4. #include "bsp_SysTick.h"


  5. #define   RC522_DELAY()  Delay_us ( 200 )

  6. /**
  7.   * @brief  向RC522发送1 Byte 数据
  8.   * @param  byte,要发送的数据
  9.   * @retval RC522返回的数据
  10.   */
  11. void SPI_RC522_SendByte ( uint8_t byte )
  12. {
  13.   uint8_t counter;

  14.   for(counter=0;counter<8;counter++)
  15.   {     
  16.     if ( byte & 0x80 )
  17.       RC522_MOSI_1 ();
  18.     else
  19.       RC522_MOSI_0 ();
  20.    
  21.     RC522_DELAY();
  22.     RC522_SCK_0 ();
  23.    
  24.     RC522_DELAY();
  25.     RC522_SCK_1();
  26.    
  27.     RC522_DELAY();
  28.     byte <<= 1;
  29.   }         
  30. }


  31. /**
  32.   * @brief  从RC522发送1 Byte 数据
  33.   * @param  无
  34.   * @retval RC522返回的数据
  35.   */
  36. uint8_t SPI_RC522_ReadByte ( void )
  37. {
  38.   uint8_t counter;
  39.   uint8_t SPI_Data;

  40.   for(counter=0;counter<8;counter++)
  41.   {
  42.     SPI_Data <<= 1;
  43.     RC522_SCK_0 ();
  44.    
  45.     RC522_DELAY();
  46.     if ( RC522_MISO_GET() == 1)
  47.      SPI_Data |= 0x01;
  48.    
  49.     RC522_DELAY();
  50.     RC522_SCK_1 ();
  51.    
  52.     RC522_DELAY();
  53.   }
  54.   return SPI_Data;
  55.         
  56. }



  57. /**
  58.   * @brief  读RC522寄存器
  59.   * @param  ucAddress,寄存器地址
  60.   * @retval 寄存器的当前值
  61.   */
  62. uint8_t ReadRawRC ( uint8_t ucAddress )
  63. {
  64.         uint8_t ucAddr, ucReturn;
  65.         
  66.         ucAddr = ( ( ucAddress << 1 ) & 0x7E ) | 0x80;        
  67.         RC522_CS_Enable();
  68.   
  69.         SPI_RC522_SendByte ( ucAddr );
  70.         ucReturn = SPI_RC522_ReadByte ();
  71.   
  72.         RC522_CS_Disable();
  73.         
  74.         return ucReturn;        
  75. }

  76. /**
  77.   * @brief  写RC522寄存器
  78.   * @param  ucAddress,寄存器地址
  79.   * @param  ucValue,写入寄存器的值
  80.   * @retval 无
  81.   */
  82. void WriteRawRC ( uint8_t ucAddress, uint8_t ucValue )
  83. {  
  84.         uint8_t ucAddr;
  85.         
  86.         ucAddr = ( ucAddress << 1 ) & 0x7E;        
  87.         RC522_CS_Enable();
  88.         
  89.         SPI_RC522_SendByte ( ucAddr );        
  90.         SPI_RC522_SendByte ( ucValue );
  91.   
  92.         RC522_CS_Disable();               
  93. }


  94. /**
  95.   * @brief  对RC522寄存器置位
  96.   * @param  ucReg,寄存器地址
  97.   * @param   ucMask,置位值
  98.   * @retval 无
  99.   */
  100. void SetBitMask ( uint8_t ucReg, uint8_t ucMask )  
  101. {
  102.   uint8_t ucTemp;

  103.   ucTemp = ReadRawRC ( ucReg );
  104.   WriteRawRC ( ucReg, ucTemp | ucMask ); // set bit mask
  105. }


  106. /**
  107.   * @brief  对RC522寄存器清位
  108.   * @param  ucReg,寄存器地址
  109.   * @param  ucMask,清位值
  110.   * @retval 无
  111.   */
  112. void ClearBitMask ( uint8_t ucReg, uint8_t ucMask )  
  113. {
  114.   uint8_t ucTemp;

  115.   ucTemp = ReadRawRC ( ucReg );
  116.   WriteRawRC ( ucReg, ucTemp & ( ~ ucMask) ); // clear bit mask
  117. }


  118. /**
  119.   * @brief  开启天线
  120.   * @param  无
  121.   * @retval 无
  122.   */
  123. void PcdAntennaOn ( void )
  124. {
  125.   uint8_t uc;

  126.   uc = ReadRawRC ( TxControlReg );
  127.   if ( ! ( uc & 0x03 ) )
  128.    SetBitMask(TxControlReg, 0x03);               
  129. }


  130. /**
  131.   * @brief  关闭天线
  132.   * @param  无
  133.   * @retval 无
  134.   */
  135. void PcdAntennaOff ( void )
  136. {
  137.   ClearBitMask ( TxControlReg, 0x03 );        
  138. }


  139. /**
  140.   * @brief  复位RC522
  141.   * @param  无
  142.   * @retval 无
  143.   */
  144. void PcdReset ( void )
  145. {
  146.         RC522_Reset_Disable();
  147.         Delay_us ( 1 );
  148.         
  149.         RC522_Reset_Enable();
  150.         Delay_us ( 1 );
  151.         
  152.         RC522_Reset_Disable();
  153.         Delay_us ( 1 );
  154.         
  155.         WriteRawRC ( CommandReg, 0x0f );
  156.         
  157.         while ( ReadRawRC ( CommandReg ) & 0x10 );
  158.         
  159.         Delay_us ( 1 );
  160.   
  161.         //定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363
  162.   WriteRawRC ( ModeReg, 0x3D );        
  163.         
  164.   WriteRawRC ( TReloadRegL, 30 );      //16位定时器低位   
  165.         WriteRawRC ( TReloadRegH, 0 );                         //16位定时器高位
  166.         
  167.   WriteRawRC ( TModeReg, 0x8D );                         //定义内部定时器的设置
  168.         
  169.   WriteRawRC ( TPrescalerReg, 0x3E );         //设置定时器分频系数
  170.         
  171.         WriteRawRC ( TxAutoReg, 0x40 );                         //调制发送信号为100%ASK        
  172.         
  173. }



  174. /**
  175.   * @brief  设置RC522的工作方式
  176.   * @param  ucType,工作方式
  177.   * @retval 无
  178.   */
  179. void M500PcdConfigISOType ( uint8_t ucType )
  180. {
  181.         if ( ucType == 'A')                     //ISO14443_A
  182.   {
  183.                 ClearBitMask ( Status2Reg, 0x08 );
  184.                
  185.     WriteRawRC ( ModeReg, 0x3D );         //3F
  186.                
  187.                 WriteRawRC ( RxSelReg, 0x86 );        //84
  188.                
  189.                 WriteRawRC( RFCfgReg, 0x7F );         //4F
  190.                
  191.                 WriteRawRC( TReloadRegL, 30 );        
  192.                
  193.                 WriteRawRC ( TReloadRegH, 0 );
  194.                
  195.                 WriteRawRC ( TModeReg, 0x8D );
  196.                
  197.                 WriteRawRC ( TPrescalerReg, 0x3E );
  198.                
  199.                 Delay_us ( 2 );
  200.                
  201.                 PcdAntennaOn ();//开天线
  202.                
  203.    }         
  204. }



  205. /**
  206.   * @brief  通过RC522和ISO14443卡通讯
  207.   * @param  ucCommand,RC522命令字
  208.   * @param  pInData,通过RC522发送到卡片的数据
  209.   * @param  ucInLenByte,发送数据的字节长度
  210.   * @param  pOutData,接收到的卡片返回数据
  211.   * @param  pOutLenBit,返回数据的位长度
  212.   * @retval 状态值= MI_OK,成功
  213.   */
  214. char PcdComMF522 ( uint8_t ucCommand,
  215.                    uint8_t * pInData,
  216.                    uint8_t ucInLenByte,
  217.                    uint8_t * pOutData,
  218.                    uint32_t * pOutLenBit )               
  219. {
  220.   char cStatus = MI_ERR;
  221.   uint8_t ucIrqEn   = 0x00;
  222.   uint8_t ucWaitFor = 0x00;
  223.   uint8_t ucLastBits;
  224.   uint8_t ucN;
  225.   uint32_t ul;

  226.   switch ( ucCommand )
  227.   {
  228.      case PCD_AUTHENT:                  //Mifare认证
  229.         ucIrqEn   = 0x12;                //允许错误中断请求ErrIEn  允许空闲中断IdleIEn
  230.         ucWaitFor = 0x10;                //认证寻卡等待时候 查询空闲中断标志位
  231.         break;
  232.      
  233.      case PCD_TRANSCEIVE:                //接收发送 发送接收
  234.         ucIrqEn   = 0x77;                //允许TxIEn RxIEn IdleIEn LoAlertIEn ErrIEn TimerIEn
  235.         ucWaitFor = 0x30;                //寻卡等待时候 查询接收中断标志位与 空闲中断标志位
  236.         break;
  237.      
  238.      default:
  239.        break;     
  240.   }
  241.   //IRqInv置位管脚IRQ与Status1Reg的IRq位的值相反
  242.   WriteRawRC ( ComIEnReg, ucIrqEn | 0x80 );
  243.   //Set1该位清零时,CommIRqReg的屏蔽位清零
  244.   ClearBitMask ( ComIrqReg, 0x80 );         
  245.   //写空闲命令
  246.   WriteRawRC ( CommandReg, PCD_IDLE );                 
  247.   
  248.   //置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除
  249.   SetBitMask ( FIFOLevelReg, 0x80 );                        

  250.   for ( ul = 0; ul < ucInLenByte; ul ++ )
  251.     WriteRawRC ( FIFODataReg, pInData [ ul ] ); //写数据进FIFOdata
  252.    
  253.   WriteRawRC ( CommandReg, ucCommand );                                        //写命令


  254.   if ( ucCommand == PCD_TRANSCEIVE )
  255.    
  256.     //StartSend置位启动数据发送 该位与收发命令使用时才有效
  257.     SetBitMask(BitFramingReg,0x80);                                    

  258.   ul = 1000;                             //根据时钟频率调整,操作M1卡最大等待时间25ms

  259.   do                                                                                                                          //认证 与寻卡等待时间        
  260.   {
  261.        ucN = ReadRawRC ( ComIrqReg );                 //查询事件中断
  262.        ul --;
  263.   } while ( ( ul != 0 ) && ( ! ( ucN & 0x01 ) ) && ( ! ( ucN & ucWaitFor ) ) );        

  264.   ClearBitMask ( BitFramingReg, 0x80 );         //清理允许StartSend位

  265.   if ( ul != 0 )
  266.   {
  267.     //读错误标志寄存器BufferOfI CollErr ParityErr ProtocolErr
  268.     if ( ! ( ReadRawRC ( ErrorReg ) & 0x1B ) )        
  269.     {
  270.       cStatus = MI_OK;
  271.       
  272.       if ( ucN & ucIrqEn & 0x01 )                                //是否发生定时器中断
  273.         cStatus = MI_NOTAGERR;   
  274.         
  275.       if ( ucCommand == PCD_TRANSCEIVE )
  276.       {
  277.         //读FIFO中保存的字节数
  278.         ucN = ReadRawRC ( FIFOLevelReg );                          
  279.         
  280.         //最后接收到得字节的有效位数
  281.         ucLastBits = ReadRawRC ( ControlReg ) & 0x07;        
  282.         
  283.         if ( ucLastBits )
  284.          
  285.           //N个字节数减去1(最后一个字节)+最后一位的位数 读取到的数据总位数
  286.           * pOutLenBit = ( ucN - 1 ) * 8 + ucLastBits;           
  287.         else
  288.           * pOutLenBit = ucN * 8;      //最后接收到的字节整个字节有效
  289.         
  290.         if ( ucN == 0 )               
  291.           ucN = 1;   
  292.         
  293.         if ( ucN > MAXRLEN )
  294.           ucN = MAXRLEN;   
  295.         
  296.         for ( ul = 0; ul < ucN; ul ++ )
  297.           pOutData [ ul ] = ReadRawRC ( FIFODataReg );   
  298.         
  299.         }        
  300.     }   
  301.     else
  302.       cStatus = MI_ERR;      
  303.   }

  304.   SetBitMask ( ControlReg, 0x80 );           // stop timer now
  305.   WriteRawRC ( CommandReg, PCD_IDLE );
  306.    
  307.   return cStatus;
  308. }

  309. /**
  310.   * @brief 寻卡
  311.   * @param  ucReq_code,寻卡方式 = 0x52,寻感应区内所有符合14443A标准的卡;
  312.             寻卡方式= 0x26,寻未进入休眠状态的卡
  313.   * @param  pTagType,卡片类型代码
  314.              = 0x4400,Mifare_UltraLight
  315.              = 0x0400,Mifare_One(S50)
  316.              = 0x0200,Mifare_One(S70)
  317.              = 0x0800,Mifare_Pro(X))
  318.              = 0x4403,Mifare_DESFire
  319.   * @retval 状态值= MI_OK,成功
  320.   */
  321. char PcdRequest ( uint8_t ucReq_code, uint8_t * pTagType )
  322. {
  323.   char cStatus;  
  324.   uint8_t ucComMF522Buf [ MAXRLEN ];
  325.   uint32_t ulLen;

  326.   //清理指示MIFARECyptol单元接通以及所有卡的数据通信被加密的情况
  327.   ClearBitMask ( Status2Reg, 0x08 );
  328.         //发送的最后一个字节的 七位
  329.   WriteRawRC ( BitFramingReg, 0x07 );
  330.   //TX1,TX2管脚的输出信号传递经发送调制的13.56的能量载波信号
  331.   SetBitMask ( TxControlReg, 0x03 );        

  332.   ucComMF522Buf [ 0 ] = ucReq_code;                //存入 卡片命令字

  333.   cStatus = PcdComMF522 ( PCD_TRANSCEIVE,        
  334.                           ucComMF522Buf,
  335.                           1,
  336.                           ucComMF522Buf,
  337.                           & ulLen );        //寻卡  

  338.   if ( ( cStatus == MI_OK ) && ( ulLen == 0x10 ) )        //寻卡成功返回卡类型
  339.   {   
  340.      * pTagType = ucComMF522Buf [ 0 ];
  341.      * ( pTagType + 1 ) = ucComMF522Buf [ 1 ];
  342.   }

  343.   else
  344.    cStatus = MI_ERR;

  345.   return cStatus;         
  346. }

  347. /**
  348.   * @brief  防冲撞
  349.   * @param  pSnr,卡片序列号,4字节
  350.   * @retval 状态值= MI_OK,成功
  351.   */
  352. char PcdAnticoll ( uint8_t * pSnr )
  353. {
  354.   char cStatus;
  355.   uint8_t uc, ucSnr_check = 0;
  356.   uint8_t ucComMF522Buf [ MAXRLEN ];
  357.   uint32_t ulLen;
  358.   
  359.   //清MFCryptol On位 只有成功执行MFAuthent命令后,该位才能置位
  360.   ClearBitMask ( Status2Reg, 0x08 );
  361.   //清理寄存器 停止收发
  362.   WriteRawRC ( BitFramingReg, 0x00);        
  363.         //清ValuesAfterColl所有接收的位在冲突后被清除
  364.   ClearBitMask ( CollReg, 0x80 );                          

  365.   ucComMF522Buf [ 0 ] = 0x93;                  //卡片防冲突命令
  366.   ucComMF522Buf [ 1 ] = 0x20;

  367.   cStatus = PcdComMF522 ( PCD_TRANSCEIVE,
  368.                           ucComMF522Buf,
  369.                           2,
  370.                           ucComMF522Buf,
  371.                           & ulLen);      //与卡片通信

  372.   if ( cStatus == MI_OK)                            //通信成功
  373.   {
  374.     for ( uc = 0; uc < 4; uc ++ )
  375.     {
  376.        * ( pSnr + uc )  = ucComMF522Buf [ uc ]; //读出UID
  377.        ucSnr_check ^= ucComMF522Buf [ uc ];
  378.     }
  379.    
  380.     if ( ucSnr_check != ucComMF522Buf [ uc ] )
  381.       cStatus = MI_ERR;                                    
  382.   }
  383.   
  384.   SetBitMask ( CollReg, 0x80 );
  385.       
  386.   return cStatus;               
  387. }


  388. /**
  389.   * @brief  用RC522计算CRC16
  390.   * @param  pIndata,计算CRC16的数组
  391.   * @param  ucLen,计算CRC16的数组字节长度
  392.   * @param  pOutData,存放计算结果存放的首地址
  393.   * @retval 无
  394.   */
  395. void CalulateCRC ( uint8_t * pIndata,
  396.                  uint8_t ucLen,
  397.                  uint8_t * pOutData )
  398. {
  399.   uint8_t uc, ucN;

  400.   ClearBitMask(DivIrqReg,0x04);

  401.   WriteRawRC(CommandReg,PCD_IDLE);

  402.   SetBitMask(FIFOLevelReg,0x80);

  403.   for ( uc = 0; uc < ucLen; uc ++)
  404.     WriteRawRC ( FIFODataReg, * ( pIndata + uc ) );   

  405.   WriteRawRC ( CommandReg, PCD_CALCCRC );

  406.   uc = 0xFF;

  407.   do
  408.   {
  409.       ucN = ReadRawRC ( DivIrqReg );
  410.       uc --;
  411.   } while ( ( uc != 0 ) && ! ( ucN & 0x04 ) );
  412.   
  413.   pOutData [ 0 ] = ReadRawRC ( CRCResultRegL );
  414.   pOutData [ 1 ] = ReadRawRC ( CRCResultRegM );               
  415. }


  416. /**
  417.   * @brief  选定卡片
  418.   * @param  pSnr,卡片序列号,4字节
  419.   * @retval 状态值= MI_OK,成功
  420.   */
  421. char PcdSelect ( uint8_t * pSnr )
  422. {
  423.   char ucN;
  424.   uint8_t uc;
  425.   uint8_t ucComMF522Buf [ MAXRLEN ];
  426.   uint32_t  ulLen;
  427.   
  428.   
  429.   ucComMF522Buf [ 0 ] = PICC_ANTICOLL1;
  430.   ucComMF522Buf [ 1 ] = 0x70;
  431.   ucComMF522Buf [ 6 ] = 0;

  432.   for ( uc = 0; uc < 4; uc ++ )
  433.   {
  434.     ucComMF522Buf [ uc + 2 ] = * ( pSnr + uc );
  435.     ucComMF522Buf [ 6 ] ^= * ( pSnr + uc );
  436.   }
  437.   
  438.   CalulateCRC ( ucComMF522Buf, 7, & ucComMF522Buf [ 7 ] );

  439.   ClearBitMask ( Status2Reg, 0x08 );

  440.   ucN = PcdComMF522 ( PCD_TRANSCEIVE,
  441.                      ucComMF522Buf,
  442.                      9,
  443.                      ucComMF522Buf,
  444.                      & ulLen );
  445.   
  446.   if ( ( ucN == MI_OK ) && ( ulLen == 0x18 ) )
  447.     ucN = MI_OK;  
  448.   else
  449.     ucN = MI_ERR;   
  450.   
  451.   return ucN;               
  452. }



  453. /**
  454.   * @brief  验证卡片密码
  455.   * @param  ucAuth_mode,密码验证模式= 0x60,验证A密钥,
  456.             密码验证模式= 0x61,验证B密钥
  457.   * @param  uint8_t ucAddr,块地址
  458.   * @param  pKey,密码
  459.   * @param  pSnr,卡片序列号,4字节
  460.   * @retval 状态值= MI_OK,成功
  461.   */
  462. char PcdAuthState ( uint8_t ucAuth_mode,
  463.                     uint8_t ucAddr,
  464.                     uint8_t * pKey,
  465.                     uint8_t * pSnr )
  466. {
  467.   char cStatus;
  468.   uint8_t uc, ucComMF522Buf [ MAXRLEN ];
  469.   uint32_t ulLen;
  470.   

  471.   ucComMF522Buf [ 0 ] = ucAuth_mode;
  472.   ucComMF522Buf [ 1 ] = ucAddr;

  473.   for ( uc = 0; uc < 6; uc ++ )
  474.     ucComMF522Buf [ uc + 2 ] = * ( pKey + uc );   

  475.   for ( uc = 0; uc < 6; uc ++ )
  476.     ucComMF522Buf [ uc + 8 ] = * ( pSnr + uc );   

  477.   cStatus = PcdComMF522 ( PCD_AUTHENT,
  478.                           ucComMF522Buf,
  479.                           12,
  480.                           ucComMF522Buf,
  481.                           & ulLen );

  482.   if ( ( cStatus != MI_OK ) || ( ! ( ReadRawRC ( Status2Reg ) & 0x08 ) ) )
  483.     cStatus = MI_ERR;   
  484.    
  485.   return cStatus;
  486. }


  487. /**
  488.   * @brief  写数据到M1卡一块
  489.   * @param  uint8_t ucAddr,块地址
  490.   * @param  pData,写入的数据,16字节
  491.   * @retval 状态值= MI_OK,成功
  492.   */
  493. char PcdWrite ( uint8_t ucAddr, uint8_t * pData )
  494. {
  495.   char cStatus;
  496.   uint8_t uc, ucComMF522Buf [ MAXRLEN ];
  497.   uint32_t ulLen;
  498.    
  499.   
  500.   ucComMF522Buf [ 0 ] = PICC_WRITE;
  501.   ucComMF522Buf [ 1 ] = ucAddr;

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

  503.   cStatus = PcdComMF522 ( PCD_TRANSCEIVE,
  504.                           ucComMF522Buf,
  505.                           4,
  506.                           ucComMF522Buf,
  507.                           & ulLen );

  508.   if ( ( cStatus != MI_OK ) || ( ulLen != 4 ) ||
  509.          ( ( ucComMF522Buf [ 0 ] & 0x0F ) != 0x0A ) )
  510.     cStatus = MI_ERR;   
  511.       
  512.   if ( cStatus == MI_OK )
  513.   {
  514.     //memcpy(ucComMF522Buf, pData, 16);
  515.     for ( uc = 0; uc < 16; uc ++ )
  516.       ucComMF522Buf [ uc ] = * ( pData + uc );  
  517.    
  518.     CalulateCRC ( ucComMF522Buf, 16, & ucComMF522Buf [ 16 ] );

  519.     cStatus = PcdComMF522 ( PCD_TRANSCEIVE,
  520.                            ucComMF522Buf,
  521.                            18,
  522.                            ucComMF522Buf,
  523.                            & ulLen );
  524.    
  525.     if ( ( cStatus != MI_OK ) || ( ulLen != 4 ) ||
  526.          ( ( ucComMF522Buf [ 0 ] & 0x0F ) != 0x0A ) )
  527.       cStatus = MI_ERR;   
  528.    
  529.   }         
  530.   return cStatus;               
  531. }


  532. /**
  533.   * @brief  读取M1卡一块数据
  534.   * @param  ucAddr,块地址
  535.   * @param  pData,读出的数据,16字节
  536.   * @retval 状态值= MI_OK,成功
  537.   */
  538. char PcdRead ( uint8_t ucAddr, uint8_t * pData )
  539. {
  540.   char cStatus;
  541.   uint8_t uc, ucComMF522Buf [ MAXRLEN ];
  542.   uint32_t ulLen;
  543.   
  544.   ucComMF522Buf [ 0 ] = PICC_READ;
  545. ……………………

  546. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
F103-指南者开发板配套例程.rar (343.49 KB, 下载次数: 25)
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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