嵌入式外设 -- 读卡器模块(RC522)

目录

一、前言

二、资料获取

关注微信公众号--星之援工作室 发送关键字(RC522)

三、代码编写

rc522_config.c

rc522_config.h

main

 四、参考


一、前言

RC522读卡器是一种常用的射频识别模块,通常用于与RFID标签进行通信。它可以读取和写入RFID标签上的信息,常见于门禁系统、智能卡、物联网设备等领域。RC522读卡器具有简单易用的特点,通过SPI接口与微控制器通信,适用于各种嵌入式系统和DIY项目。

二、资料获取

关注微信公众号--星之援工作室 发送关键字(RC522)

这里的话直接是采用的网上开源的资料进行书写,借花献佛咯

➡️🫡🫡🫡🫡🫡🫡🫡🫡➡️

 三、代码编写

注意事项:这款设备是采用模拟 SPI 的方式进行控制和读取的,所以大家可以自由规划 io 口使用(实例程序的接口如下)

rc522_config.c


#include "rc522_config.h"
#include "stm32f10x.h"

static void             RC522_SPI_Config             ( void );

/**
  * @brief  RC522_Init
  * @param  无
  * @retval 无
  */
void RC522_Init ( void )
{
	RC522_SPI_Config ();	
	RC522_Reset_Disable();	
	RC522_CS_Disable();
}

/**
  * @brief  R522 SPI配置
  * @param  无
  * @retval 无
  */
static void RC522_SPI_Config ( void )
{
  /* SPI_InitTypeDef  SPI_InitStructure */
  GPIO_InitTypeDef GPIO_InitStructure;
  
	/*!< Configure SPI_RC522_SPI pins: CS */
	RC522_GPIO_CS_CLK_FUN ( RC522_GPIO_CS_CLK, ENABLE );
  GPIO_InitStructure.GPIO_Pin = RC522_GPIO_CS_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = RC522_GPIO_CS_Mode;
  GPIO_Init(RC522_GPIO_CS_PORT, &GPIO_InitStructure);
	
  /*!< Configure SPI_RC522_SPI pins: SCK */
	RC522_GPIO_SCK_CLK_FUN ( RC522_GPIO_SCK_CLK, ENABLE );
  GPIO_InitStructure.GPIO_Pin = RC522_GPIO_SCK_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = RC522_GPIO_SCK_Mode;
  GPIO_Init(RC522_GPIO_SCK_PORT, &GPIO_InitStructure);
	
  /*!< Configure SPI_RC522_SPI pins: MOSI */
	RC522_GPIO_MOSI_CLK_FUN ( RC522_GPIO_MOSI_CLK, ENABLE );
  GPIO_InitStructure.GPIO_Pin = RC522_GPIO_MOSI_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = RC522_GPIO_MOSI_Mode;
  GPIO_Init(RC522_GPIO_MOSI_PORT, &GPIO_InitStructure);

  /*!< Configure SPI_RC522_SPI pins: MISO */
	RC522_GPIO_MISO_CLK_FUN ( RC522_GPIO_MISO_CLK, ENABLE );
  GPIO_InitStructure.GPIO_Pin = RC522_GPIO_MISO_PIN;
  GPIO_InitStructure.GPIO_Mode = RC522_GPIO_MISO_Mode;
  GPIO_Init(RC522_GPIO_MISO_PORT, &GPIO_InitStructure);	
		
  /*!< Configure SPI_RC522_SPI pins: RST */
	RC522_GPIO_RST_CLK_FUN ( RC522_GPIO_RST_CLK, ENABLE );
  GPIO_InitStructure.GPIO_Pin = RC522_GPIO_RST_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = RC522_GPIO_RST_Mode;
  GPIO_Init(RC522_GPIO_RST_PORT, &GPIO_InitStructure);
	
}


rc522_config.h


#ifndef __RC522_CONFIG_H
#define	__RC522_CONFIG_H



/
//MF522命令字
/
#define PCD_IDLE              0x00               //取消当前命令
#define PCD_AUTHENT           0x0E               //验证密钥
#define PCD_RECEIVE           0x08               //接收数据
#define PCD_TRANSMIT          0x04               //发送数据
#define PCD_TRANSCEIVE        0x0C               //发送并接收数据
#define PCD_RESETPHASE        0x0F               //复位
#define PCD_CALCCRC           0x03               //CRC计算

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

/
//MF522 FIFO长度定义
/
#define DEF_FIFO_LENGTH       64                 //FIFO size=64byte
#define MAXRLEN  18

/
//MF522寄存器定义
/
// PAGE 0
#define     RFU00                 0x00    
#define     CommandReg            0x01    
#define     ComIEnReg             0x02    
#define     DivlEnReg             0x03    
#define     ComIrqReg             0x04    
#define     DivIrqReg             0x05
#define     ErrorReg              0x06    
#define     Status1Reg            0x07    
#define     Status2Reg            0x08    
#define     FIFODataReg           0x09
#define     FIFOLevelReg          0x0A
#define     WaterLevelReg         0x0B
#define     ControlReg            0x0C
#define     BitFramingReg         0x0D
#define     CollReg               0x0E
#define     RFU0F                 0x0F
// PAGE 1     
#define     RFU10                 0x10
#define     ModeReg               0x11
#define     TxModeReg             0x12
#define     RxModeReg             0x13
#define     TxControlReg          0x14
#define     TxAutoReg             0x15
#define     TxSelReg              0x16
#define     RxSelReg              0x17
#define     RxThresholdReg        0x18
#define     DemodReg              0x19
#define     RFU1A                 0x1A
#define     RFU1B                 0x1B
#define     MifareReg             0x1C
#define     RFU1D                 0x1D
#define     RFU1E                 0x1E
#define     SerialSpeedReg        0x1F
// PAGE 2    
#define     RFU20                 0x20  
#define     CRCResultRegM         0x21
#define     CRCResultRegL         0x22
#define     RFU23                 0x23
#define     ModWidthReg           0x24
#define     RFU25                 0x25
#define     RFCfgReg              0x26
#define     GsNReg                0x27
#define     CWGsCfgReg            0x28
#define     ModGsCfgReg           0x29
#define     TModeReg              0x2A
#define     TPrescalerReg         0x2B
#define     TReloadRegH           0x2C
#define     TReloadRegL           0x2D
#define     TCounterValueRegH     0x2E
#define     TCounterValueRegL     0x2F
// PAGE 3      
#define     RFU30                 0x30
#define     TestSel1Reg           0x31
#define     TestSel2Reg           0x32
#define     TestPinEnReg          0x33
#define     TestPinValueReg       0x34
#define     TestBusReg            0x35
#define     AutoTestReg           0x36
#define     VersionReg            0x37
#define     AnalogTestReg         0x38
#define     TestDAC1Reg           0x39  
#define     TestDAC2Reg           0x3A   
#define     TestADCReg            0x3B   
#define     RFU3C                 0x3C   
#define     RFU3D                 0x3D   
#define     RFU3E                 0x3E   
#define     RFU3F		  		        0x3F

/
//和MF522通讯时返回的错误代码
/
#define 	MI_OK                 0x26
#define 	MI_NOTAGERR           0xcc
#define 	MI_ERR                0xbb

 
 
/*********************************** RC522 引脚定义 *********************************************/
//RC522模块有除了电源还有6个数据引脚,其中IRQ不需要使用,悬空即可,剩下的5个数据引脚连接如下:
//如果RC522需要修改与STM32的连接,则修改这些IO即可,但必须连接到STM32的SPI引脚
//片选,即RC522模块的SDA引脚
#define               RC522_GPIO_CS_CLK_FUN                  RCC_APB2PeriphClockCmd
#define               RC522_GPIO_CS_CLK                      RCC_APB2Periph_GPIOA
#define               RC522_GPIO_CS_PORT    	               GPIOA			   
#define               RC522_GPIO_CS_PIN		                   GPIO_Pin_3
#define               RC522_GPIO_CS_Mode		                 GPIO_Mode_Out_PP

//时钟,即RC522模块的SCK引脚,接STM32的SPI的SCK引脚
#define               RC522_GPIO_SCK_CLK_FUN                 RCC_APB2PeriphClockCmd
#define               RC522_GPIO_SCK_CLK                     RCC_APB2Periph_GPIOA
#define               RC522_GPIO_SCK_PORT    	               GPIOA			   
#define               RC522_GPIO_SCK_PIN		                 GPIO_Pin_5
#define               RC522_GPIO_SCK_Mode		                 GPIO_Mode_Out_PP

// 数据输入,即即RC522模块的MOSI引脚,接STM32的SPI的MOSI引脚
#define               RC522_GPIO_MOSI_CLK_FUN                RCC_APB2PeriphClockCmd
#define               RC522_GPIO_MOSI_CLK                    RCC_APB2Periph_GPIOA
#define               RC522_GPIO_MOSI_PORT    	             GPIOA			   
#define               RC522_GPIO_MOSI_PIN		                 GPIO_Pin_7
#define               RC522_GPIO_MOSI_Mode		               GPIO_Mode_Out_PP

// 数据输出,即即RC522模块的MISO引脚,接STM32的SPI的MISO引脚
#define               RC522_GPIO_MISO_CLK_FUN                RCC_APB2PeriphClockCmd
#define               RC522_GPIO_MISO_CLK                    RCC_APB2Periph_GPIOA
#define               RC522_GPIO_MISO_PORT    	             GPIOA			   
#define               RC522_GPIO_MISO_PIN		                 GPIO_Pin_6
#define               RC522_GPIO_MISO_Mode		               GPIO_Mode_IN_FLOATING

//复位,即即RC522模块的RST引脚,接STM32的普通IO即可
#define               RC522_GPIO_RST_CLK_FUN                 RCC_APB2PeriphClockCmd
#define               RC522_GPIO_RST_CLK                     RCC_APB2Periph_GPIOA
#define               RC522_GPIO_RST_PORT    	               GPIOA		   
#define               RC522_GPIO_RST_PIN		                 GPIO_Pin_2
#define               RC522_GPIO_RST_Mode		                 GPIO_Mode_Out_PP



/*********************************** RC522 函数宏定义*********************************************/
#define          RC522_CS_Enable()         GPIO_ResetBits ( RC522_GPIO_CS_PORT, RC522_GPIO_CS_PIN )
#define          RC522_CS_Disable()        GPIO_SetBits ( RC522_GPIO_CS_PORT, RC522_GPIO_CS_PIN )

#define          RC522_Reset_Enable()      GPIO_ResetBits( RC522_GPIO_RST_PORT, RC522_GPIO_RST_PIN )
#define          RC522_Reset_Disable()     GPIO_SetBits ( RC522_GPIO_RST_PORT, RC522_GPIO_RST_PIN )

#define          RC522_SCK_0()             GPIO_ResetBits( RC522_GPIO_SCK_PORT, RC522_GPIO_SCK_PIN )
#define          RC522_SCK_1()             GPIO_SetBits ( RC522_GPIO_SCK_PORT, RC522_GPIO_SCK_PIN )

#define          RC522_MOSI_0()            GPIO_ResetBits( RC522_GPIO_MOSI_PORT, RC522_GPIO_MOSI_PIN )
#define          RC522_MOSI_1()            GPIO_SetBits ( RC522_GPIO_MOSI_PORT, RC522_GPIO_MOSI_PIN )

#define          RC522_MISO_GET()          GPIO_ReadInputDataBit ( RC522_GPIO_MISO_PORT, RC522_GPIO_MISO_PIN )



/*********************************** 函数 *********************************************/
void             RC522_Init                   ( void );



#endif /* __RC522_CONFIG_H */

main

/**
  ******************************************************************************
  * @file    main.c
  * @author  fire
  * @version V1.0
  * @date    2013-xx-xx
  * @brief   RFID-RC522模块实验
  ******************************************************************************
  */ 

#include "stm32f10x.h"
#include "bsp_SysTick.h"
#include "bsp_usart1.h"
#include "rc522_config.h"
#include "rc522_function.h"
#include <stdbool.h>
#include "bsp_lcd.h"
#include "./font/fonts.h"
#include "./key/bsp_key.h"  


extern uint16_t lcdid;


uint8_t KeyValue[]={0xFF ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF};   // 卡A密钥
//uint8_t KeyValue[]={'1' ,'2', '3', '4', '5', '6'};   // 卡A密钥

/**
  * @brief  IC测试函数
  * @param  无
  * @retval 无
  */
void IC_test ( void )
{
	uint32_t writeValue = 100;
	uint32_t readValue;
	char cStr [ 30 ];
  uint8_t ucArray_ID [ 4 ];    /*先后存放IC卡的类型和UID(IC卡序列号)*/                                                                                         
	uint8_t ucStatusReturn;      /*返回状态*/                                                                                           
  while ( 1 )
  {    
    /*寻卡*/
		if ( ( ucStatusReturn = PcdRequest ( PICC_REQALL, ucArray_ID ) ) != MI_OK )
    {
      /*若失败再次寻卡*/
      printf ( "寻卡失败\n" );
			ucStatusReturn = PcdRequest ( PICC_REQALL, ucArray_ID ); //PICC_REQALL   PICC_REQIDL
    }	                                                

		if ( ucStatusReturn == MI_OK  )
		{
      //printf ( "寻卡成功\n" );
      /*防冲撞(当有多张卡进入读写器操作范围时,防冲突机制会从其中选择一张进行操作)*/
			if ( PcdAnticoll ( ucArray_ID ) == MI_OK )                                                                   
			{
				PcdSelect(ucArray_ID);			
		
				PcdAuthState( PICC_AUTHENT1A, 0x11, KeyValue, ucArray_ID );//校验密码 
        WriteAmount(0x11,writeValue); //写入金额
        if(ReadAmount(0x11,&readValue) == MI_OK)	//读取金额
				{		
					//writeValue +=100;
				  sprintf ( cStr, "The Card ID is: %02X%02X%02X%02X",ucArray_ID [0], ucArray_ID [1], ucArray_ID [2],ucArray_ID [3] );
					printf ( "%s\r\n",cStr );  //打印卡片ID
          ILI9341_DispStringLine_EN(LINE(0), cStr);
					
					printf ("余额为:%d\r\n",readValue);
					sprintf ( cStr, "TThe residual amount: %d", readValue);				 										 	         
					ILI9341_DispStringLine_EN(LINE(1), cStr );
          PcdHalt();
				}
        
        /* 按键1检测 */
        if( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON  )
        {
          printf("金额 +100\r\n");
          writeValue += 100;
        }
        /* 按键2检测 */
        if( Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_ON  )
        {
          printf("金额 -100\r\n");
          writeValue -= 100;
        }
			}				
		}		
		    
  }	
}

/**
  * @brief  主函数
  * @param  无
  * @retval 无
  */
int main ( void )
{
  /*滴答时钟初始化*/
	SysTick_Init ();   
	
  /*USART1 配置模式为 115200 8-N-1,中断接收 */
	USART1_Config ();
  
  /* Key 初始化 */
  Key_GPIO_Config();
	
  /*RC522模块所需外设的初始化配置*/
	RC522_Init ();     
	
  /*LCD 初始化*/
	LCD_Init ();  
  
  //判断一下LCD内部IC
  if(lcdid == LCDID_ILI9341)
  {
    ILI9341_GramScan ( 6 );
  }
  else if(lcdid == LCDID_ST7789V)
  {
    ILI9341_GramScan ( 0 );
  }
  
	printf ( "WF-RC522 Test\n" );
	
	LCD_SetFont(&Font8x16);
	LCD_SetColors(RED,BLACK);

  /* 清屏,显示全黑 */
  ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH);	
	ILI9341_DispStringLine_EN(LINE(13), 
         "Please put the IC card on WF-RC522 antenna area ..." );
	
	LCD_SetTextColor(BLUE);
	
	PcdReset ();
  
  /*设置工作方式*/
	M500PcdConfigISOType ( 'A' );
	
	
  while ( 1 )
  {
    /*IC卡检测	*/
    IC_test ();
  }	
}



/****************************END OF FILE**********************/

 四、参考

 野火资料库icon-default.png?t=N7T8https://doc.embedfire.com/products/link/zh/latest/index.htmlRC522模块学习icon-default.png?t=N7T8https://blog.csdn.net/hbzdsXCV/article/details/128132423?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171625709616800182718369%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=171625709616800182718369&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-2-128132423-null-null.142^v100^pc_search_result_base7&utm_term=RC522&spm=1018.2226.3001.4187


///////////////////////////////////////////////////////////////////// //功 能:寻卡 //参数说明: req_code[IN]:寻卡方式 // 0x52 = 寻感应区内所有符合14443A标准的卡 // 0x26 = 寻未进入休眠状态的卡 // pTagType[OUT]:卡片类型代码 // 0x4400 = Mifare_UltraLight // 0x0400 = Mifare_One(S50) // 0x0200 = Mifare_One(S70) // 0x0800 = Mifare_Pro(X) // 0x4403 = Mifare_DESFire //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// signed char PcdRequest(unsigned char req_code,unsigned char *pTagType) { signed char status; unsigned int unLen; unsigned char ucComMF522Buf[MAXRLEN]; ClearBitMask(Status2Reg,0x08); WriteRawRC(BitFramingReg,0x07); SetBitMask(TxControlReg,0x03); ucComMF522Buf[0] = req_code; status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen;); if ((status == MI_OK) && (unLen == 0x10)) { *pTagType = ucComMF522Buf[0]; *(pTagType+1) = ucComMF522Buf[1]; } else { status = MI_ERR; } return status; } ///////////////////////////////////////////////////////////////////// //功 能:防冲撞 //参数说明: pSnr[OUT]:卡片序列号,4字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// signed char PcdAnticoll(unsigned char *pSnr) { signed char status; unsigned char i,snr_check=0; unsigned int unLen; unsigned char ucComMF522Buf[MAXRLEN]; ClearBitMask(Status2Reg,0x08); WriteRawRC(BitFramingReg,0x00); ClearBitMask(CollReg,0x80); ucComMF522Buf[0] = PICC_ANTICOLL1; ucComMF522Buf[1] = 0x20; status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen;); if (status == MI_OK) { for (i=0; i<4; i++) { *(pSnr+i) = ucComMF522Buf[i]; snr_check ^= ucComMF522Buf[i]; } if (snr_check != ucComMF522Buf[i]) { status = MI_ERR; } } SetBitMask(CollReg,0x80); return status; } ///////////////////////////////////////////////////////////////////// //功 能:选定卡片 //参数说明: pSnr[IN]:卡片序列号,4字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// signed char PcdSelect(unsigned char *pSnr) { signed char status; unsigned char i; unsigned int unLen; unsigned char ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = PICC_ANTICOLL1; ucComMF522Buf[1] = 0x70; ucComMF522Buf[6] = 0; for (i=0; i<4; i++) { ucComMF522Buf[i+2] = *(pSnr+i); ucComMF522Buf[6] ^= *(pSnr+i); } CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf;[7]); ClearBitMask(Status2Reg,0x08); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen;); if ((status == MI_OK) && (unLen == 0x18)) { status = MI_OK; } else { status = MI_ERR; } return status; } ///////////////////////////////////////////////////////////////////// //功 能:验证卡片密码 //参数说明: auth_mode[IN]: 密码验证模式 // 0x60 = 验证A密钥 // 0x61 = 验证B密钥 // addr[IN]:块地址 // pKey[IN]:密码 // pSnr[IN]:卡片序列号,4字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// signed char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr) { signed char status; unsigned int unLen; unsigned char i,ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = auth_mode; ucComMF522Buf[1] = addr; for (i=0; i<6; i++) { ucComMF522Buf[i+2] = *(pKey+i); } for (i=0; i<6; i++) { ucComMF522Buf[i+8] = *(pSnr+i); } // memcpy(&ucComMF522Buf;[2], pKey, 6); // memcpy(&ucComMF522Buf;[8], pSnr, 4); status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen;); if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08))) { status = MI_ERR; } return status; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿柒学起来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值