[STM32F4] STM32F407——RC522(模拟SPI)

[复制链接]
 楼主| 无法去污粉 发表于 2022-12-25 13:40 | 显示全部楼层 |阅读模式

1.引脚连接

MISO——PA6

MOSI——PA7

SCK——PA5

NSS——PA4

RST——PA8

IRQ悬空不接引脚

2.GPIO配置

MISO配置成浮空输入,其余的配置出推挽输出

    1. #include "bsp_spi.h"


    2. static void RC522_SPI_Config(void);



    3. void RC522_Init ( void )
    4. {
    5.        
    6.         RC522_SPI_Config ();       
    7.         RC522_Reset_Disable();       
    8.         RC522_CS_Disable();
    9.        
    10. }


    11. /**
    12.   * [url=home.php?mod=space&uid=247401]@brief[/url]  模拟软件SPI初始化
    13.   * @param  无
    14.   * @retval 无
    15.   */
    16.        
    17. static void RC522_SPI_Config(void)
    18. {
    19.   GPIO_InitTypeDef GPIO_InitStructure;
    20.   
    21.   //使能GPIO时钟
    22.         RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);
    23.        

    24.         //MISO
    25.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    26.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //输入
    27.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  //浮空:无上拉和下拉
    28.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    29.         GPIO_Init(GPIOA, &GPIO_InitStructure);
    30.                
    31.         //MOSI
    32.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    33.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    34.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    35.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    36.         GPIO_Init(GPIOA, &GPIO_InitStructure);
    37.        
    38.         //SCK
    39.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    40.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    41.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    42.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    43.   GPIO_Init(GPIOA, &GPIO_InitStructure);


    44.         //NSS
    45.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    46.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    47.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    48.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    49.   GPIO_Init(GPIOA, &GPIO_InitStructure);
    50.        
    51.         //RST
    52.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    53.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    54.         GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    55.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    56.   GPIO_Init(GPIOA, &GPIO_InitStructure);


    57. }





评论

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_47316662/article/details/124555292 ———————————————— 版权声明:本文为CSDN博主「半透明的橙子i」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_47316662/arti  发表于 2022-12-25 13:43
 楼主| 无法去污粉 发表于 2022-12-25 13:44 | 显示全部楼层
接发数据

数据由  MISO端口——>RC522寄存器,MOSI端口<——RC522寄存器

软件SPI通过控制MISO引脚和MOSI端口引脚的高低电平来控制数据的进出,下面读取和写入寄存器的函数都是靠这两个函数来接收和发送数据与外界
6736563a7e347b7f8f.png
 楼主| 无法去污粉 发表于 2022-12-25 13:45 | 显示全部楼层
查数据手册得RC552采用模式3,上图为模式3的时序图,根据时序图写发送数据,共有8个时钟周期,所以循环8次, 按位查询需要发送的数据的高低电平,0将MOSI引输出低电平,1将MOSI输出高电平,然后调SCK时钟引脚,使时钟引脚输出低电平(默认状态高电平),延时一会,输出高电平,
 楼主| 无法去污粉 发表于 2022-12-25 13:46 | 显示全部楼层
  1. void SPI_RC522_SendByte ( uint8_t byte )
  2. {
  3.   uint8_t counter;

  4.   for(counter=0;counter<8;counter++)
  5.   {     
  6.     if ( byte & 0x80 )
  7.       RC522_MOSI_1 ();
  8.     else
  9.       RC522_MOSI_0 ();
  10.    
  11.     RC522_DELAY();
  12.     RC522_SCK_0 ();
  13.    
  14.     RC522_DELAY();
  15.     RC522_SCK_1();
  16.    
  17.     RC522_DELAY();
  18.     byte <<= 1;
  19.   }        
  20. }


  21. /**
  22.   * @brief  从RC522发送1 Byte 数据
  23.   * @param  无
  24.   * @retval RC522返回的数据
  25.   */
  26. uint8_t SPI_RC522_ReadByte ( void )
  27. {
  28.   uint8_t counter;
  29.   uint8_t SPI_Data;

  30.   for(counter=0;counter<8;counter++)
  31.   {
  32.     SPI_Data <<= 1;
  33.     RC522_SCK_0 ();
  34.    
  35.     RC522_DELAY();
  36.     if ( RC522_MISO_GET() == 1)
  37.      SPI_Data |= 0x01;
  38.    
  39.     RC522_DELAY();
  40.     RC522_SCK_1 ();
  41.    
  42.     RC522_DELAY();
  43.   }
  44.   return SPI_Data;
  45.        
  46. }
 楼主| 无法去污粉 发表于 2022-12-25 13:46 | 显示全部楼层
RC522官方函数

RC522.c

  1. **
  2.   * @brief  读RC522寄存器
  3.   * @param  ucAddress,寄存器地址
  4.   * @retval 寄存器的当前值
  5.   */
  6. uint8_t ReadRawRC ( uint8_t ucAddress )
  7. {
  8.         uint8_t ucAddr, ucReturn;
  9.        
  10.         ucAddr = ( ( ucAddress << 1 ) & 0x7E ) | 0x80;       
  11.         RC522_CS_Enable();
  12.   
  13.         SPI_RC522_SendByte ( ucAddr );
  14.         ucReturn = SPI_RC522_ReadByte ();
  15.   
  16.         RC522_CS_Disable();
  17.        
  18.         return ucReturn;       
  19. }

  20. /**
  21.   * @brief  写RC522寄存器
  22.   * @param  ucAddress,寄存器地址
  23.   * @param  ucValue,写入寄存器的值
  24.   * @retval 无
  25.   */
  26. void WriteRawRC ( uint8_t ucAddress, uint8_t ucValue )
  27. {  
  28.         uint8_t ucAddr;
  29.        
  30.         ucAddr = ( ucAddress << 1 ) & 0x7E;       
  31.         RC522_CS_Enable();
  32.        
  33.         SPI_RC522_SendByte ( ucAddr );       
  34.         SPI_RC522_SendByte ( ucValue );
  35.   
  36.         RC522_CS_Disable();               
  37. }


  38. /**
  39.   * @brief  对RC522寄存器置位
  40.   * @param  ucReg,寄存器地址
  41.   * @param   ucMask,置位值
  42.   * @retval 无
  43.   */
  44. void SetBitMask ( uint8_t ucReg, uint8_t ucMask )  
  45. {
  46.   uint8_t ucTemp;

  47.   ucTemp = ReadRawRC ( ucReg );
  48.   WriteRawRC ( ucReg, ucTemp | ucMask ); // set bit mask
  49. }


  50. /**
  51.   * @brief  对RC522寄存器清位
  52.   * @param  ucReg,寄存器地址
  53.   * @param  ucMask,清位值
  54.   * @retval 无
  55.   */
  56. void ClearBitMask ( uint8_t ucReg, uint8_t ucMask )  
  57. {
  58.   uint8_t ucTemp;

  59.   ucTemp = ReadRawRC ( ucReg );
  60.   WriteRawRC ( ucReg, ucTemp & ( ~ ucMask) ); // clear bit mask
  61. }


  62. /**
  63.   * @brief  开启天线
  64.   * @param  无
  65.   * @retval 无
  66.   */
  67. void PcdAntennaOn ( void )
  68. {
  69.   uint8_t uc;

  70.   uc = ReadRawRC ( TxControlReg );
  71.   if ( ! ( uc & 0x03 ) )
  72.    SetBitMask(TxControlReg, 0x03);               
  73. }


  74. /**
  75.   * @brief  关闭天线
  76.   * @param  无
  77.   * @retval 无
  78.   */
  79. void PcdAntennaOff ( void )
  80. {
  81.   ClearBitMask ( TxControlReg, 0x03 );       
  82. }


  83. /**
  84.   * @brief  复位RC522
  85.   * @param  无
  86.   * @retval 无
  87.   */
  88. void PcdReset ( void )
  89. {
  90.         RC522_Reset_Disable();
  91.        
  92.         Delay_us ( 1 );
  93.        
  94.         RC522_Reset_Enable();
  95.         Delay_us ( 1 );
  96.        
  97.         RC522_Reset_Disable();
  98.         Delay_us ( 1 );
  99.        
  100.        
  101.         WriteRawRC ( CommandReg, 0x0f );
  102.        
  103.         while ( ReadRawRC ( CommandReg ) & 0x10 );
  104.        
  105.         Delay_us ( 1 );
  106.   
  107.         //定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363
  108.   WriteRawRC ( ModeReg, 0x3D );        
  109.        
  110.   WriteRawRC ( TReloadRegL, 30 );      //16位定时器低位   
  111.         WriteRawRC ( TReloadRegH, 0 );                         //16位定时器高位
  112.        
  113.   WriteRawRC ( TModeReg, 0x8D );                         //定义内部定时器的设置
  114.        
  115.   WriteRawRC ( TPrescalerReg, 0x3E );         //设置定时器分频系数
  116.        
  117.         WriteRawRC ( TxAutoReg, 0x40 );                         //调制发送信号为100%ASK       
  118.        
  119. }



  120. /**
  121.   * @brief  设置RC522的工作方式
  122.   * @param  ucType,工作方式
  123.   * @retval 无
  124.   */
  125. void M500PcdConfigISOType ( uint8_t ucType )
  126. {
  127.         if ( ucType == 'A')                     //ISO14443_A
  128.   {
  129.                 ClearBitMask ( Status2Reg, 0x08 );
  130.                
  131.     WriteRawRC ( ModeReg, 0x3D );         //3F
  132.                
  133.                 WriteRawRC ( RxSelReg, 0x86 );        //84
  134.                
  135.                 WriteRawRC( RFCfgReg, 0x7F );         //4F
  136.                
  137.                 WriteRawRC( TReloadRegL, 30 );        
  138.                
  139.                 WriteRawRC ( TReloadRegH, 0 );
  140.                
  141.                 WriteRawRC ( TModeReg, 0x8D );
  142.                
  143.                 WriteRawRC ( TPrescalerReg, 0x3E );
  144.                
  145.                 Delay_us ( 2 );
  146.                
  147.                 PcdAntennaOn ();//开天线
  148.                
  149.    }         
  150. }



  151. /**
  152.   * @brief  通过RC522和ISO14443卡通讯
  153.   * @param  ucCommand,RC522命令字
  154.   * @param  pInData,通过RC522发送到卡片的数据
  155.   * @param  ucInLenByte,发送数据的字节长度
  156.   * @param  pOutData,接收到的卡片返回数据
  157.   * @param  pOutLenBit,返回数据的位长度
  158.   * @retval 状态值= MI_OK,成功
  159.   */
  160. char PcdComMF522 ( uint8_t ucCommand,
  161.                    uint8_t * pInData,
  162.                    uint8_t ucInLenByte,
  163.                    uint8_t * pOutData,
  164.                    uint32_t * pOutLenBit )               
  165. {
  166.   char cStatus = MI_ERR;
  167.   uint8_t ucIrqEn   = 0x00;
  168.   uint8_t ucWaitFor = 0x00;
  169.   uint8_t ucLastBits;
  170.   uint8_t ucN;
  171.   uint32_t ul;

  172.   switch ( ucCommand )
  173.   {
  174.      case PCD_AUTHENT:                  //Mifare认证
  175.         ucIrqEn   = 0x12;                //允许错误中断请求ErrIEn  允许空闲中断IdleIEn
  176.         ucWaitFor = 0x10;                //认证寻卡等待时候 查询空闲中断标志位
  177.         break;
  178.      
  179.      case PCD_TRANSCEIVE:                //接收发送 发送接收
  180.         ucIrqEn   = 0x77;                //允许TxIEn RxIEn IdleIEn LoAlertIEn ErrIEn TimerIEn
  181.         ucWaitFor = 0x30;                //寻卡等待时候 查询接收中断标志位与 空闲中断标志位
  182.         break;
  183.      
  184.      default:
  185.        break;     
  186.   }
  187.   //IRqInv置位管脚IRQ与Status1Reg的IRq位的值相反
  188.   WriteRawRC ( ComIEnReg, ucIrqEn | 0x80 );
  189.   //Set1该位清零时,CommIRqReg的屏蔽位清零
  190.   ClearBitMask ( ComIrqReg, 0x80 );         
  191.   //写空闲命令
  192.   WriteRawRC ( CommandReg, PCD_IDLE );                 
  193.   
  194.   //置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除
  195.   SetBitMask ( FIFOLevelReg, 0x80 );                       

  196.   for ( ul = 0; ul < ucInLenByte; ul ++ )
  197.     WriteRawRC ( FIFODataReg, pInData [ ul ] ); //写数据进FIFOdata
  198.    
  199.   WriteRawRC ( CommandReg, ucCommand );                                        //写命令


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

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

  205.   do                                                                                                                          //认证 与寻卡等待时间       
  206.   {
  207.        ucN = ReadRawRC ( ComIrqReg );                 //查询事件中断
  208.        ul --;
  209.   } while ( ( ul != 0 ) && ( ! ( ucN & 0x01 ) ) && ( ! ( ucN & ucWaitFor ) ) );        //退出条件i=0,定时器中断,与写空闲命令

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

  211.   if ( ul != 0 )
  212.   {
  213.     //读错误标志寄存器BufferOfI CollErr ParityErr ProtocolErr
  214.     if ( ! ( ReadRawRC ( ErrorReg ) & 0x1B ) )       
  215.     {
  216.       cStatus = MI_OK;
  217.       
  218.       if ( ucN & ucIrqEn & 0x01 )                                //是否发生定时器中断
  219.         cStatus = MI_NOTAGERR;   
  220.         
  221.       if ( ucCommand == PCD_TRANSCEIVE )
  222.       {
  223.         //读FIFO中保存的字节数
  224.         ucN = ReadRawRC ( FIFOLevelReg );                          
  225.         
  226.         //最后接收到得字节的有效位数
  227.         ucLastBits = ReadRawRC ( ControlReg ) & 0x07;       
  228.         
  229.         if ( ucLastBits )
  230.          
  231.           //N个字节数减去1(最后一个字节)+最后一位的位数 读取到的数据总位数
  232.           * pOutLenBit = ( ucN - 1 ) * 8 + ucLastBits;          
  233.         else
  234.           * pOutLenBit = ucN * 8;      //最后接收到的字节整个字节有效
  235.         
  236.         if ( ucN == 0 )               
  237.           ucN = 1;   
  238.         
  239.         if ( ucN > MAXRLEN )
  240.           ucN = MAXRLEN;   
  241.         
  242.         for ( ul = 0; ul < ucN; ul ++ )
  243.           pOutData [ ul ] = ReadRawRC ( FIFODataReg );   
  244.         
  245.         }        
  246.     }   
  247.     else
  248.       cStatus = MI_ERR;      
  249.   }

  250.   SetBitMask ( ControlReg, 0x80 );           // stop timer now
  251.   WriteRawRC ( CommandReg, PCD_IDLE );
  252.    
  253.   return cStatus;
  254. }

  255. /**
  256.   * @brief 寻卡
  257.   * @param  ucReq_code,寻卡方式 = 0x52,寻感应区内所有符合14443A标准的卡;
  258.             寻卡方式= 0x26,寻未进入休眠状态的卡
  259.   * @param  pTagType,卡片类型代码
  260.              = 0x4400,Mifare_UltraLight
  261.              = 0x0400,Mifare_One(S50)
  262.              = 0x0200,Mifare_One(S70)
  263.              = 0x0800,Mifare_Pro(X))
  264.              = 0x4403,Mifare_DESFire
  265.   * @retval 状态值= MI_OK,成功
  266.   */
  267. char PcdRequest ( uint8_t ucReq_code, uint8_t * pTagType )
  268. {
  269.   char cStatus;  
  270.   uint8_t ucComMF522Buf [ MAXRLEN ];
  271.   uint32_t ulLen;

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

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

  279.   cStatus = PcdComMF522 ( PCD_TRANSCEIVE,       
  280.                           ucComMF522Buf,
  281.                           1,
  282.                           ucComMF522Buf,
  283.                           & ulLen );        //寻卡  

  284.   if ( ( cStatus == MI_OK ) && ( ulLen == 0x10 ) )        //寻卡成功返回卡类型
  285.   {   
  286.      * pTagType = ucComMF522Buf [ 0 ];
  287.      * ( pTagType + 1 ) = ucComMF522Buf [ 1 ];
  288.   }

  289.   else
  290.    cStatus = MI_ERR;

  291.   return cStatus;         
  292. }

  293. /**
  294.   * @brief  防冲撞
  295.   * @param  pSnr,卡片序列号,4字节
  296.   * @retval 状态值= MI_OK,成功
  297.   */
  298. char PcdAnticoll ( uint8_t * pSnr )
  299. {
  300.   char cStatus;
  301.   uint8_t uc, ucSnr_check = 0;
  302.   uint8_t ucComMF522Buf [ MAXRLEN ];
  303.   uint32_t ulLen;
  304.   
  305.   //清MFCryptol On位 只有成功执行MFAuthent命令后,该位才能置位
  306.   ClearBitMask ( Status2Reg, 0x08 );
  307.   //清理寄存器 停止收发
  308.   WriteRawRC ( BitFramingReg, 0x00);       
  309.         //清ValuesAfterColl所有接收的位在冲突后被清除
  310.   ClearBitMask ( CollReg, 0x80 );                          

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

  313.   cStatus = PcdComMF522 ( PCD_TRANSCEIVE,
  314.                           ucComMF522Buf,
  315.                           2,
  316.                           ucComMF522Buf,
  317.                           & ulLen);      //与卡片通信

  318.   if ( cStatus == MI_OK)                            //通信成功
  319.   {
  320.     for ( uc = 0; uc < 4; uc ++ )
  321.     {
  322.        * ( pSnr + uc )  = ucComMF522Buf [ uc ]; //读出UID
  323.        ucSnr_check ^= ucComMF522Buf [ uc ];
  324.     }
  325.    
  326.     if ( ucSnr_check != ucComMF522Buf [ uc ] )
  327.       cStatus = MI_ERR;                                     
  328.   }
  329.   
  330.   SetBitMask ( CollReg, 0x80 );
  331.       
  332.   return cStatus;               
  333. }


  334. /**
  335.   * @brief  用RC522计算CRC16
  336.   * @param  pIndata,计算CRC16的数组
  337.   * @param  ucLen,计算CRC16的数组字节长度
  338.   * @param  pOutData,存放计算结果存放的首地址
  339.   * @retval 无
  340.   */
  341. void CalulateCRC ( uint8_t * pIndata,
  342.                  uint8_t ucLen,
  343.                  uint8_t * pOutData )
  344. {
  345.   uint8_t uc, ucN;

  346.   ClearBitMask(DivIrqReg,0x04);

  347.   WriteRawRC(CommandReg,PCD_IDLE);

  348.   SetBitMask(FIFOLevelReg,0x80);

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

  351.   WriteRawRC ( CommandReg, PCD_CALCCRC );

  352.   uc = 0xFF;

  353.   do
  354.   {
  355.       ucN = ReadRawRC ( DivIrqReg );
  356.       uc --;
  357.   } while ( ( uc != 0 ) && ! ( ucN & 0x04 ) );
  358.   
  359.   pOutData [ 0 ] = ReadRawRC ( CRCResultRegL );
  360.   pOutData [ 1 ] = ReadRawRC ( CRCResultRegM );               
  361. }


  362. /**
  363.   * @brief  选定卡片
  364.   * @param  pSnr,卡片序列号,4字节
  365.   * @retval 状态值= MI_OK,成功
  366.   */
  367. char PcdSelect ( uint8_t * pSnr )
  368. {
  369.   char ucN;
  370.   uint8_t uc;
  371.   uint8_t ucComMF522Buf [ MAXRLEN ];
  372.   uint32_t  ulLen;
  373.   
  374.   
  375.   ucComMF522Buf [ 0 ] = PICC_ANTICOLL1;
  376.   ucComMF522Buf [ 1 ] = 0x70;
  377.   ucComMF522Buf [ 6 ] = 0;

  378.   for ( uc = 0; uc < 4; uc ++ )
  379.   {
  380.     ucComMF522Buf [ uc + 2 ] = * ( pSnr + uc );
  381.     ucComMF522Buf [ 6 ] ^= * ( pSnr + uc );
  382.   }
  383.   
  384.   CalulateCRC ( ucComMF522Buf, 7, & ucComMF522Buf [ 7 ] );

  385.   ClearBitMask ( Status2Reg, 0x08 );

  386.   ucN = PcdComMF522 ( PCD_TRANSCEIVE,
  387.                      ucComMF522Buf,
  388.                      9,
  389.                      ucComMF522Buf,
  390.                      & ulLen );
  391.   
  392.   if ( ( ucN == MI_OK ) && ( ulLen == 0x18 ) )
  393.     ucN = MI_OK;  
  394.   else
  395.     ucN = MI_ERR;   
  396.   
  397.   return ucN;               
  398. }



  399. /**
  400.   * @brief  验证卡片密码
  401.   * @param  ucAuth_mode,密码验证模式= 0x60,验证A密钥,
  402.             密码验证模式= 0x61,验证B密钥
  403.   * @param  uint8_t ucAddr,块地址
  404.   * @param  pKey,密码
  405.   * @param  pSnr,卡片序列号,4字节
  406.   * @retval 状态值= MI_OK,成功
  407.   */
  408. char PcdAuthState ( uint8_t ucAuth_mode,
  409.                     uint8_t ucAddr,
  410.                     uint8_t * pKey,
  411.                     uint8_t * pSnr )
  412. {
  413.   char cStatus;
  414.   uint8_t uc, ucComMF522Buf [ MAXRLEN ];
  415.   uint32_t ulLen;
  416.   

  417.   ucComMF522Buf [ 0 ] = ucAuth_mode;
  418.   ucComMF522Buf [ 1 ] = ucAddr;

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

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

  423.   cStatus = PcdComMF522 ( PCD_AUTHENT,
  424.                           ucComMF522Buf,
  425.                           12,
  426.                           ucComMF522Buf,
  427.                           & ulLen );

  428.   if ( ( cStatus != MI_OK ) || ( ! ( ReadRawRC ( Status2Reg ) & 0x08 ) ) )
  429.     cStatus = MI_ERR;   
  430.    
  431.   return cStatus;
  432. }


  433. /**
  434.   * @brief  写数据到M1卡一块
  435.   * @param  ucAddr,块地址(0-63)。M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
  436.   * @param  pData,写入的数据,16字节
  437.   * @retval 状态值= MI_OK,成功
  438.   */
  439. char PcdWrite ( uint8_t ucAddr, uint8_t * pData )
  440. {
  441.   char cStatus;
  442.   uint8_t uc, ucComMF522Buf [ MAXRLEN ];
  443.   uint32_t ulLen;
  444.    
  445.   
  446.   ucComMF522Buf [ 0 ] = PICC_WRITE;
  447.   ucComMF522Buf [ 1 ] = ucAddr;

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

  449.   cStatus = PcdComMF522 ( PCD_TRANSCEIVE,
  450.                           ucComMF522Buf,
  451.                           4,
  452.                           ucComMF522Buf,
  453.                           & ulLen );

  454.   if ( ( cStatus != MI_OK ) || ( ulLen != 4 ) ||
  455.          ( ( ucComMF522Buf [ 0 ] & 0x0F ) != 0x0A ) )
  456.     cStatus = MI_ERR;   
  457.       
  458.   if ( cStatus == MI_OK )
  459.   {
  460.     //memcpy(ucComMF522Buf, pData, 16);
  461.     for ( uc = 0; uc < 16; uc ++ )
  462.       ucComMF522Buf [ uc ] = * ( pData + uc );  
  463.    
  464.     CalulateCRC ( ucComMF522Buf, 16, & ucComMF522Buf [ 16 ] );

  465.     cStatus = PcdComMF522 ( PCD_TRANSCEIVE,
  466.                            ucComMF522Buf,
  467.                            18,
  468.                            ucComMF522Buf,
  469.                            & ulLen );
  470.    
  471.     if ( ( cStatus != MI_OK ) || ( ulLen != 4 ) ||
  472.          ( ( ucComMF522Buf [ 0 ] & 0x0F ) != 0x0A ) )
  473.       cStatus = MI_ERR;   
  474.    
  475.   }        
  476.   return cStatus;               
  477. }


  478. /**
  479.   * @brief  读取M1卡一块数据
  480.   * @param  ucAddr,块地址(0-63)。M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
  481.   * @param  pData,读出的数据,16字节
  482.   * @retval 状态值= MI_OK,成功
  483.   */
  484. char PcdRead ( uint8_t ucAddr, uint8_t * pData )
  485. {
  486.   char cStatus;
  487.   uint8_t uc, ucComMF522Buf [ MAXRLEN ];
  488.   uint32_t ulLen;
  489.   
  490.   ucComMF522Buf [ 0 ] = PICC_READ;
  491.   ucComMF522Buf [ 1 ] = ucAddr;

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

  493.   cStatus = PcdComMF522 ( PCD_TRANSCEIVE,
  494.                           ucComMF522Buf,
  495.                           4,
  496.                           ucComMF522Buf,
  497.                           & ulLen );

  498.   if ( ( cStatus == MI_OK ) && ( ulLen == 0x90 ) )
  499.   {
  500.     for ( uc = 0; uc < 16; uc ++ )
  501.       * ( pData + uc ) = ucComMF522Buf [ uc ];   
  502.   }
  503.   
  504.   else
  505.     cStatus = MI_ERR;   
  506.    
  507.   return cStatus;               
  508. }



  509. /**
  510.   * @brief  判断 ucAddr 是否数据块
  511.   * @param  ucAddr,块绝对地址(0-63)
  512.   * @retval 返回值 1:是数据块;0:不是数据块
  513.   */
  514. char IsDataBlock( uint8_t ucAddr )
  515. {
  516.   if(ucAddr == 0)
  517.   {
  518.     printf("第0扇区的块0不可更改,不应对其进行操作\r\n");
  519.     return 0;
  520.   }
  521.   /* 如果是数据块(不包含数据块0) */
  522.   if( (ucAddr<64) && (((ucAddr+1)%4) != 0) )
  523.   {
  524.     return 1;
  525.   }
  526.   
  527.   printf("块地址不是指向数据块\r\n");
  528.   return 0;
  529. }

  530. /**
  531.   * @brief  写 pData 字符串到M1卡中的数据块
  532.   * @param  ucAddr,数据块地址(不能写入控制块)
  533.   * @param  pData,写入的数据,16字节
  534.   * @retval 状态值= MI_OK,成功
  535.   */
  536. char PcdWriteString ( uint8_t ucAddr, uint8_t * pData )
  537. {
  538.   /* 如果是数据块(不包含数据块0),则写入 */
  539.   if( IsDataBlock(ucAddr) )
  540.   {
  541.     return PcdWrite(ucAddr, pData);
  542.   }

  543.   return MI_ERR;
  544. }

  545. /**
  546.   * @brief  读取M1卡中的一块数据到 pData
  547.   * @param  ucAddr,数据块地址(不读取控制块)
  548.   * @param  pData,读出的数据,16字节
  549.   * @retval 状态值= MI_OK,成功
  550.   */
  551. char PcdReadString ( uint8_t ucAddr, uint8_t * pData )
  552. {
  553.   /* 如果是数据块(不包含数据块0),则读取 */
  554.   if( IsDataBlock(ucAddr) )
  555.   {
  556.     return PcdRead(ucAddr, pData);
  557.   }

  558.   return MI_ERR;
  559. }



  560. /**
  561.   * @brief  命令卡片进入休眠状态
  562.   * @param  无
  563.   * @retval 状态值= MI_OK,成功
  564.   */
  565. char PcdHalt( void )
  566. {
  567.         uint8_t ucComMF522Buf [ MAXRLEN ];
  568.         uint32_t  ulLen;
  569.   

  570.   ucComMF522Buf [ 0 ] = PICC_HALT;
  571.   ucComMF522Buf [ 1 ] = 0;
  572.        
  573.   CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );
  574.         PcdComMF522 ( PCD_TRANSCEIVE,
  575.                 ucComMF522Buf,
  576.                 4,
  577.                 ucComMF522Buf,
  578.                 & ulLen );

  579.   return MI_OK;       
  580. }

  581. /
  582. //功    能:写入钱包金额
  583. //参数说明: ucAddr[IN]:块地址
  584. //          pData:写入的金额
  585. //返    回: 成功返回MI_OK
  586. /
  587. char WriteAmount( uint8_t ucAddr, uint32_t pData )
  588. {
  589.         char status;
  590.         uint8_t ucComMF522Buf[16];
  591.         ucComMF522Buf[0] = (pData&((uint32_t)0x000000ff));
  592.         ucComMF522Buf[1] = (pData&((uint32_t)0x0000ff00))>>8;
  593.         ucComMF522Buf[2] = (pData&((uint32_t)0x00ff0000))>>16;
  594.         ucComMF522Buf[3] = (pData&((uint32_t)0xff000000))>>24;       
  595.        
  596.         ucComMF522Buf[4] = ~(pData&((uint32_t)0x000000ff));
  597.         ucComMF522Buf[5] = ~(pData&((uint32_t)0x0000ff00))>>8;
  598.         ucComMF522Buf[6] = ~(pData&((uint32_t)0x00ff0000))>>16;
  599.         ucComMF522Buf[7] = ~(pData&((uint32_t)0xff000000))>>24;       
  600.        
  601.         ucComMF522Buf[8] = (pData&((uint32_t)0x000000ff));
  602.         ucComMF522Buf[9] = (pData&((uint32_t)0x0000ff00))>>8;
  603.         ucComMF522Buf[10] = (pData&((uint32_t)0x00ff0000))>>16;
  604.         ucComMF522Buf[11] = (pData&((uint32_t)0xff000000))>>24;       
  605.        
  606.         ucComMF522Buf[12] = ucAddr;
  607.         ucComMF522Buf[13] = ~ucAddr;
  608.         ucComMF522Buf[14] = ucAddr;
  609.         ucComMF522Buf[15] = ~ucAddr;
  610.   status = PcdWrite(ucAddr,ucComMF522Buf);
  611.         return status;
  612. }

  613. /
  614. //功    能:读取钱包金额
  615. //参数说明: ucAddr[IN]:块地址
  616. //          *pData:读出的金额
  617. //返    回: 成功返回MI_OK
  618. /
  619. char ReadAmount( uint8_t ucAddr, uint32_t *pData )
  620. {
  621.        
  622.         char status = MI_ERR;
  623.         uint8_t j;
  624.         uint8_t ucComMF522Buf[16];
  625.   status = PcdRead(ucAddr,ucComMF522Buf);
  626.         if(status != MI_OK)
  627.                 return status;
  628.         for(j=0;j<4;j++)
  629.         {
  630.                 if((ucComMF522Buf[j] != ucComMF522Buf[j+8]) && (ucComMF522Buf[j] != ~ucComMF522Buf[j+4]))//验证一下是不是钱包的数据
  631.                 break;
  632.         }
  633.         if(j == 4)
  634.         {
  635.                   status = MI_OK;
  636.                         *pData = ucComMF522Buf[0] + (ucComMF522Buf[1]<<8) + (ucComMF522Buf[2]<<16) + (ucComMF522Buf[3]<<24);
  637.         }
  638.         else
  639.         {
  640.                 status = MI_ERR;
  641.                 *pData = 0;
  642.         }
  643.   return status;       
  644. }





  645. /**
  646. * @brief 修改控制块 ucAddr 的密码A。注意 ucAddr 指的是控制块的地址。
  647. *        必须要校验密码B,密码B默认为6个0xFF,如果密码B也忘记了,那就改不了密码A了
  648. * [url=home.php?mod=space&uid=536309]@NOTE[/url]  注意:该函数仅适用于默认的存储控制模式,若是其他的话可能出现问题
  649. * @param ucAddr:[控制块]所在的地址。M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
  650. * @param pKeyA:指向新的密码A字符串,六个字符,比如 "123456"
  651. * @retval 成功返回 MI_OK
  652. */
  653. char ChangeKeyA( uint8_t ucAddr, uint8_t *pKeyA )
  654. {
  655.         uint8_t KeyBValue[]={0xFF ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // B密钥
  656.   uint8_t ucArray_ID [ 4 ];    /*先后存放IC卡的类型和UID(IC卡序列号)*/                                                                                         
  657.   uint8_t ucComMF522Buf[16];
  658.   uint8_t j;
  659.   
  660.   /*寻卡*/
  661.   while ( PcdRequest ( PICC_REQALL, ucArray_ID ) != MI_OK )
  662.   {   
  663.     printf( "寻卡失败\r\n" );
  664.     Delay_us(1000000);
  665.   }
  666.   
  667.   printf ( "寻卡成功\n" );
  668.   
  669.   /* 防冲突(当有多张卡进入读写器操作范围时,防冲突机制会从其中选择一张进行操作)*/
  670.   if ( PcdAnticoll ( ucArray_ID ) == MI_OK )                                                                  
  671.   {
  672.     /* 选中卡 */
  673.     PcdSelect(ucArray_ID);                       

  674.     /* 校验 B 密码 */
  675.     if( PcdAuthState( PICC_AUTHENT1B, ucAddr, KeyBValue, ucArray_ID ) != MI_OK )
  676.     {
  677.       printf( "检验密码B失败\r\n" );
  678.     }
  679.    
  680.     // 读取控制块里原本的数据(只要修改密码A,其他数据不改)
  681.     if( PcdRead(ucAddr,ucComMF522Buf) != MI_OK)
  682.     {
  683.       printf( "读取控制块数据失败\r\n" );
  684.       return MI_ERR;
  685.     }
  686.    
  687.     /* 修改密码A */
  688.     for(j=0; j<6; j++)
  689.       ucComMF522Buf[j] = pKeyA[j];
  690.    
  691.     if( PcdWrite(ucAddr,ucComMF522Buf) != MI_OK)
  692.     {
  693.       printf( "写入数据到控制块失败\r\n" );
  694.       return MI_ERR;
  695.     }
  696.    
  697.     printf( "密码A修改成功!\r\n" );
  698.     PcdHalt();
  699.    
  700.     return MI_OK;
  701.   }
  702.   
  703.   return MI_ERR;
  704. }


  705. /**
  706. * @brief 按照RC522操作流程写入16字节数据到块 ucAddr
  707. *        函数里校验的是密码B,密码B默认为6个0xFF,也可以校验密码A
  708. *        用法:WriteDataBlock( 1, "123456789\n", 10); //字符串不够16个字节的后面补零写入
  709. * @note  注意:该函数仅适用于默认的存储控制模式,若是其他的话可能出现问题
  710. *        注意:使用该函数要注意 ucAddr 是块0、数据块还是控制块,该函数内部不对此做判断
  711. * @param ucAddr:任意块地址。M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
  712. * @param pData:指向要写入的数据,最大16个字符
  713. * @param Len:要写入数据的字节数
  714. * @retval 成功返回 MI_OK
  715. */
  716. char WriteDataBlock( uint8_t ucAddr, uint8_t *pData, uint8_t Len)
  717. {
  718.         uint8_t KeyBValue[]={0xFF ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // B密钥
  719.   uint8_t ucArray_ID [ 4 ];    /*先后存放IC卡的类型和UID(IC卡序列号)*/                                                                                         
  720.   uint8_t ucComMF522Buf[16];
  721.   uint8_t j;
  722.   
  723.   /*寻卡*/
  724.   while ( PcdRequest ( PICC_REQALL, ucArray_ID ) != MI_OK )
  725.   {   
  726.     printf( "寻卡失败\r\n" );
  727.     Delay_us(1000000);
  728.   }
  729.   
  730.   printf ( "寻卡成功\n" );
  731.   
  732.   /* 防冲突(当有多张卡进入读写器操作范围时,防冲突机制会从其中选择一张进行操作)*/
  733.   if ( PcdAnticoll ( ucArray_ID ) == MI_OK )                                                                  
  734.   {
  735.     /* 选中卡 */
  736.     PcdSelect(ucArray_ID);                       

  737.     /* 校验 B 密码 */
  738.     if( PcdAuthState( PICC_AUTHENT1B, ucAddr, KeyBValue, ucArray_ID ) != MI_OK )
  739.     {
  740.       printf( "检验密码B失败\r\n" );
  741.     }
  742.    
  743.     /* 拷贝 pData 里的 Len 个字符到 ucComMF522Buf */
  744.     for(j=0; j<16; j++)
  745.     {
  746.       if( j < Len ) ucComMF522Buf[j] = pData[j];
  747.       else ucComMF522Buf[j] = 0; //16个字节若是未填满的字节置0
  748.     }
  749.    
  750.     /* 写入字符串 */
  751.     if( PcdWrite(ucAddr,ucComMF522Buf) != MI_OK)
  752.     {
  753.       printf( "写入数据到数据块失败\r\n" );
  754.       return MI_ERR;
  755.     }
  756.    
  757.     printf( "写入数据成功!\r\n" );
  758.     PcdHalt();
  759.    
  760.     return MI_OK;
  761.   }
  762.   
  763.   return MI_ERR;
  764. }


  765. /**
  766. * @brief 按照RC522操作流程读取块 ucAddr
  767. *        函数里校验的是密码B,密码B默认为6个0xFF,也可以校验密码A
  768. *        用法:ReadDataBlock( 1, databuf);  // databuf 至少为16字节:uint8_t databuf[16];
  769. * @note  注意:该函数仅适用于默认的存储控制模式,若是其他的话可能出现问题
  770. *        注意:使用该函数要注意 ucAddr 是块0、数据块还是控制块,该函数内部不对此做判断
  771. * @param ucAddr:任意块地址。M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
  772. * @param pData:指向读取到的数据,包含16个字符
  773. * @retval 成功返回 MI_OK
  774. */
  775. char ReadDataBlock( uint8_t ucAddr, uint8_t *pData)
  776. {
  777.         uint8_t KeyBValue[]={0xFF ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // B密钥
  778.   uint8_t ucArray_ID [ 4 ];    /*先后存放IC卡的类型和UID(IC卡序列号)*/                                                                                         
  779.   
  780.   /*寻卡*/
  781.   while ( PcdRequest ( PICC_REQALL, ucArray_ID ) != MI_OK )
  782.   {   
  783.     printf( "寻卡失败\r\n" );
  784.     Delay_us(1000000);
  785.   }
  786.   
  787.   printf ( "寻卡成功\n" );
  788.   
  789.   /* 防冲突(当有多张卡进入读写器操作范围时,防冲突机制会从其中选择一张进行操作)*/
  790.   if ( PcdAnticoll ( ucArray_ID ) == MI_OK )                                                                  
  791.   {
  792.     /* 选中卡 */
  793.     PcdSelect(ucArray_ID);                       

  794.     /* 校验 B 密码 */
  795.     if( PcdAuthState( PICC_AUTHENT1B, ucAddr, KeyBValue, ucArray_ID ) != MI_OK )
  796.     {
  797.       printf( "检验密码B失败\r\n" );
  798.     }
  799.    
  800.     // 读取数据块里的数据到 pData
  801.     if( PcdRead(ucAddr, pData) != MI_OK)
  802.     {
  803.       printf( "读取数据块失败\r\n" );
  804.       return MI_ERR;
  805.     }
  806.    
  807.     printf( "读取数据成功!\r\n" );
  808.     PcdHalt();
  809.    
  810.     return MI_OK;
  811.   }
  812.   
  813.   return MI_ERR;
  814. }

 楼主| 无法去污粉 发表于 2022-12-25 13:48 | 显示全部楼层
RC522.H
  1. #ifndef BSP_SPI_H
  2. #define BSP_SPI_H

  3. #include  "stm32f4xx.h"


  4. /
  5. //MF522命令字
  6. /
  7. #define PCD_IDLE              0x00               //取消当前命令
  8. #define PCD_AUTHENT           0x0E               //验证密钥
  9. #define PCD_RECEIVE           0x08               //接收数据
  10. #define PCD_TRANSMIT          0x04               //发送数据
  11. #define PCD_TRANSCEIVE        0x0C               //发送并接收数据
  12. #define PCD_RESETPHASE        0x0F               //复位
  13. #define PCD_CALCCRC           0x03               //CRC计算

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

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

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

  106. /
  107. //和MF522通讯时返回的错误代码
  108. /
  109. #define         MI_OK                 0x26
  110. #define         MI_NOTAGERR           0xcc
  111. #define         MI_ERR                0xbb


  112. /*********************************** RC522 函数宏定义*********************************************/
  113. #define          RC522_CS_Enable()         GPIO_ResetBits (GPIOA,GPIO_Pin_4)
  114. #define          RC522_CS_Disable()        GPIO_SetBits (GPIOA,GPIO_Pin_4)

  115. #define          RC522_Reset_Enable()      GPIO_ResetBits(GPIOA,GPIO_Pin_8)
  116. #define          RC522_Reset_Disable()     GPIO_SetBits (GPIOA,GPIO_Pin_8)

  117. #define          RC522_SCK_0()             GPIO_ResetBits(GPIOA,GPIO_Pin_5)
  118. #define          RC522_SCK_1()             GPIO_SetBits (GPIOA,GPIO_Pin_5)

  119. #define          RC522_MOSI_0()            GPIO_ResetBits(GPIOA,GPIO_Pin_7)
  120. #define          RC522_MOSI_1()            GPIO_SetBits (GPIOA,GPIO_Pin_7)

  121. #define          RC522_MISO_GET()          GPIO_ReadInputDataBit (GPIOA,GPIO_Pin_6)



  122. /*********************************** 函数 *********************************************/
  123. void             RC522_Init                   ( void );



  124. #endif /*BSP_SPI_H */
 楼主| 无法去污粉 发表于 2022-12-25 13:49 | 显示全部楼层
  1. #include "rc522.h"
  2. #include "bsp_led.h"
  3. #include "bsp_spi.h"
  4. #include "bsp_usart.h"
  5. #include "bsp_SysTick.h"



  6. uint8_t KeyValue[]={0xFF ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF};   // 卡A密钥



  7. void IC_test ( void )
  8. {
  9.         uint32_t writeValue = 100;
  10.         uint32_t readValue;
  11.         char cStr [ 30 ];
  12.   uint8_t ucArray_ID [ 4 ];    /*先后存放IC卡的类型和UID(IC卡序列号)*/                                                                                         
  13.         uint8_t ucStatusReturn;      /*返回状态*/                                                                                          
  14.   while ( 1 )
  15.   {   
  16.     /*寻卡*/
  17.                 if ( ( ucStatusReturn = PcdRequest ( PICC_REQALL, ucArray_ID ) ) != MI_OK )
  18.     {
  19.                
  20.       /*若失败再次寻卡*/
  21.       printf ( "寻卡失败\n" );
  22.                         ucStatusReturn = PcdRequest ( PICC_REQALL, ucArray_ID ); //PICC_REQALL   PICC_REQIDL
  23.     }

  24.                 if ( ucStatusReturn == MI_OK  )
  25.                 {
  26.       //printf ( "寻卡成功\n" );
  27.       /*防冲撞(当有多张卡进入读写器操作范围时,防冲突机制会从其中选择一张进行操作)*/
  28.                         if ( PcdAnticoll ( ucArray_ID ) == MI_OK )                                                                  
  29.                         {
  30.                                 PcdSelect(ucArray_ID);                       
  31.                
  32.                                 PcdAuthState( PICC_AUTHENT1A, 0x11, KeyValue, ucArray_ID );//校验密码                        
  33.         WriteAmount(0x11,writeValue); //写入金额
  34.         if(ReadAmount(0x11,&readValue) == MI_OK)        //读取金额
  35.                                 {               
  36.                                         //writeValue +=100;
  37.                                   sprintf ( cStr, "The Card ID is: %02X%02X%02X%02X",ucArray_ID [0], ucArray_ID [1], ucArray_ID [2],ucArray_ID [3] );
  38.                                         printf ( "%s\r\n",cStr );  //打印卡片ID
  39.                                        
  40.                                         printf ("余额为:%d\r\n",readValue);
  41.                                         sprintf ( cStr, "TThe residual amount: %d", readValue);                                                                                                                                  
  42.           PcdHalt();
  43.                                 }
  44.         
  45.    
  46.         
  47.                         }                               
  48.                 }               
  49.                     
  50.   }       
  51. }





  52. int main(void)
  53. {
  54.        
  55.         LED_GPIO_Config();

  56.         SysTick_Init();       //滴答时钟初始化
  57.         USART_Config(); //USART1 配置模式为 115200 8-N-1,中断接收
  58.         RC522_Init ();        //RC522模块所需外设的初始化配置
  59.         printf("reallly");
  60.        
  61.         PcdReset ();
  62.         M500PcdConfigISOType ( 'A' );//设置工作方式

  63.         printf("ok");
  64.        
  65.   while ( 1 )
  66.   {
  67.     IC_test ();//IC卡检测       
  68.   }       

  69.        
您需要登录后才可以回帖 登录 | 注册

本版积分规则

56

主题

807

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部