RFID(RadioFrequencyIdentification,射频识别技术)是一种非接触式的自动识别技术,通过射频信号自动识别目标对象并获取相关数据,广泛应用于物流、零售、交通、医疗等多个领域。以下从技术原理、组成部分、应用场景及优缺点等方面详细介绍:

1、RFID技术的基本原理

RFID技术利用无线电波进行数据传输和通信,其核心原理是电磁感应电磁反向散射耦合当RFID标签进入阅读器产生的磁场或电磁场时,标签会接收阅读器发出的射频信号,通过感应电流获得能量(被动式标签),或主动发射信号(主动式标签),将存储的信息发送给阅读器,完成识别过程。

2、RFID系统的组成部分

一个完整的RFID系统通常包括以下三个核心组件:

(1)RFID标签(Tag)相当于“电子标签”,内置芯片和天线,用于存储目标对象的识别信息(如唯一ID、物品属性等)。按供电方式可分为:被动式标签(无电池,依靠阅读器的射频能量工作,成本低、体积小,但通信距离短);主动式标签(自带电池,可主动发射信号,通信距离远,但成本高、体积较大,寿命受电池限制);半主动式标签(电池仅用于激活标签,通信仍依赖阅读器能量,平衡了距离和成本)。

(2)RFID阅读器(Reader)负责发射射频信号、接收标签返回的信息,并将数据传输到后端系统。通常包含天线、射频模块和数据处理单元,可固定安装(如门禁、仓库)或手持移动(如盘点、巡检)。

(3)后端系统(BackendSystem)包括数据库、服务器和应用软件,用于处理阅读器传输的数据,实现信息存储、查询、分析和管理(如库存统计、轨迹追踪等)。

3、RFID的典型应用场景

(1)物流与供应链管理实现货物全程追踪:在集装箱、包裹上贴RFID标签,通过阅读器快速识别货物信息,提升分拣效率和库存准确性。例如:亚马逊仓库利用RFID快速盘点商品,减少人工操作。

(2)零售与库存管理门店商品贴标签后,可通过手持阅读器快速盘点库存,避免人工扫码的繁琐;还能实现“无感结账”(如自助收银台自动识别商品并结算)。

(3)交通与门禁高速公路ETC:车辆安装RFID标签,通过收费站时自动识别并扣费,无需停车;门禁系统:员工佩戴RFID卡,靠近阅读器即可开门,替代传统钥匙。

(4)医疗健康患者腕带:存储患者身份、病历信息,医生扫码即可快速调取数据,减少人为差错;医疗器械追踪:对手术器械、药品贴标签,确保消毒流程合规,避免丢失。

(5)防伪与溯源奢侈品、烟酒等商品附唯一RFID标签,消费者可通过专用设备查询真伪和生产流程,防止假冒。

(6)畜牧业与农业给牲畜植入低频RFID标签,记录生长信息、健康状况,实现全生命周期管理;农产品溯源:通过标签记录种植、加工、运输信息,保障食品安全。

4.RFID的优缺点

优点:非接触式识别多标签同时读取存储容量大耐用性强安全性高。
缺点:成本较高易受干扰标准不统一隐私风险。

5.单片机连接硬件图:

实物图:

6.驱动思路:​

硬件连接完成后开始初始化工作,先配置 GPIO,将 SPI 相关引脚设为复用推挽输出,片选和复位引脚设为推挽输出,接着初始化 SPI 外设,设置 STM32 为 SPI 主机模式,波特率不超过 10MHz,采用模式 0(CPOL=0,CPHA=0)和 8 位数据格式,最后通过操作寄存器,让 RC522 进入初始状态。

由于 RC522 的所有功能都通过寄存器操作实现,需要封装读写寄存器的函数,写寄存器时先拉低片选,发送寄存器地址(前 4 位为地址,后 4 位为写命令 “0010”)和数据,再拉高片选;读寄存器则类似,只是地址后 4 位为读命令 “0011”,发送后读取返回数据。完成基础寄存器操作后,进行模块的核心配置,比如设置接收增益通过 RegRxGain 寄存器调整信号接收强度,配置工作频率使模块与卡片通信匹配,还要初始化天线,确保其正常发射和接收射频信号。

接下来实现卡片操作流程,首先是寻卡,通过发送寻卡命令(如 0x26)检测是否有卡片进入磁场,若成功则获取卡类型;然后进行防冲突处理,发送防冲突命令(如 0x93)解决多卡同时存在的问题,获取卡片唯一 ID;之后选卡,确认要操作的卡片;如果需要读写数据,还需进行密码验证,验证通过后才能对 M1 卡的相应数据块进行读写操作,整个过程中通过 STM32 的 SPI 通信不断与 RC522 交互,将操作结果通过串口等方式输出.

7.单片机程序代码:

main.c

#include "stm32f10x.h"  
#include "string.h"  
#include "stdio.h" 
#include "delay.h"   
#include "bsp_usart.h"
#include "oled.h"
#include "SPI.h"
#include "RC522.h"

char OLEDBUff[512];
uint8_t cardID[4] = {0};
int main(void)
{
	NVIC_PriorityGroupConfig (NVIC_PriorityGroup_2);
	SysTick_Init(72);  //系统时钟初始化 
	usart1_init(115200);//串口1初始化
	printf("USART1 OK!\r\n");
	usart2_init(115200);//串口1初始化
	usart3_init(115200);//串口3初始化	
	OLED_Init();
	SPIClass.SPI2_Init(); // SPI初始化
	MFRC522_Init(); // RC522初始化
	while(1)
	{
		memset(OLEDBUff,0,512);
		OLED_ShowString(0,0,"卡号");
		if(RC522_cardScan(cardID)==0) 
		{
			sprintf(OLEDBUff,"0x%02X%02X%02X%02X", cardID[0], cardID[1], cardID[2], cardID[3]);
		  printf("card scan success, id:0x%02X%02X%02X%02X\n", cardID[0], cardID[1], cardID[2], cardID[3]);
		}
		delay_ms(10);
		OLED_ShowString(42,0,OLEDBUff);
	}
}

Uart.c

#include "stm32f10x.h"
#include "bsp_usart.h"	  
#include "stdio.h"
#include "string.h"
#include "stm32f10x_tim.h"


////////////////////////////////////////////////////////////////////////////////// 	

//////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
int _sys_exit(int x) 
{ 
	x = x; 
	return 0;
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 	
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
	USART1->DR = (u8) ch;      
	return ch;
}
#endif
 
#if EN_USART1

UART_BUF buf_uart1;     //CH340
//初始化IO 串口1 
//bound:波特率
void usart1_init(u32 bound){
   //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
	USART_DeInit(USART1);  //复位串口1
 //USART1_TX   PA.9
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
 
	//USART1_RX	  PA.10
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA10

  //USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//一般设置为115200;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
	USART_Init(USART1, &USART_InitStructure); //初始化串口
	
	USART_Cmd(USART1, ENABLE);                    //使能串口 

	
#if EN_USART1_RX	

	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
	USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启相关中断
	USART_ClearFlag(USART1, USART_FLAG_TC);
	//Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、

#endif

}

/*********************************串口1的服务函数*************************************************/
void USART1_Send_byte(char data)
{
	while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
	USART_SendData(USART1, data);
}
/*-------------------------------------------------*/
/*函数名:串口1 发送数组                             */
/*参  数:bound:波特率                             */
/*返回值:无                                        */
/*-------------------------------------------------*/
void USART1_Send(char *Data,uint16_t Len)
{ 
	uint16_t i;
	for(i=0; i<Len; i++)
	{
		USART1_Send_byte(Data[i]);
	}
}
void USART1_SendStr(char*SendBuf)//串口1打印数据
{
	while(*SendBuf)
	{
        while((USART1->SR&0X40)==0);//等待发送完成 
        USART1->DR = (u8) *SendBuf; 
				SendBuf++;
	}
}

/*****************************************************
清空电脑反馈的缓冲数据 串口1
*****************************************************/
void Clear_Buffer_UART1(void)//清空缓存
{
    buf_uart1.index=0;
	  buf_uart1.rx_flag=0;
    memset(buf_uart1.buf,0,BUFLEN);
}
void UART1_receive_process_event(char ch )     //串口2给4g用
{
    if(buf_uart1.index >= BUFLEN)
    {
        buf_uart1.index = 0 ;
    }
    else
    {
        buf_uart1.buf[buf_uart1.index++] = ch;
    }
}

//串口1的接收中断程序
void USART1_IRQHandler(void)                                //串口1中断服务程序
{
		uint8_t Res;
		Res=Res;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断,可以扩展来控制
    {
        Res=USART_ReceiveData(USART1);//接收模块的数据;

        UART1_receive_process_event(Res);//接收模块的数据
    } 
    if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  //模块空闲
    {
        Res=USART_ReceiveData(USART1);//接收模块的数据;

				buf_uart1.rx_flag=1;
    } 

} 


#endif




#if EN_USART2
UART_BUF buf_uart2;     //EC200T
//初始化IO 串口2
//pclk1:PCLK1时钟频率(Mhz)
//bound:波特率 
void usart2_init(u32 bound)
{  	 

    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//使能,GPIOA时钟
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//USART2
		USART_DeInit(USART2);  //复位串口2
	 //USART2_TX   PA.2
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA2
   
    //USART2_RX	  PA.3
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA3

   
   //USART 初始化设置

		USART_InitStructure.USART_BaudRate = bound;//115200
		USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
		USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
		USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
		USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
		USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
    USART_Init(USART2, &USART_InitStructure); //初始化串口
    USART_Cmd(USART2, ENABLE);                    //使能串口 




#if EN_USART2_RX	
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启相关中断
		USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);//开启相关中断
		
    //Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;//串口1中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;		//子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、
#endif
}


void Clear_Buffer_UART2(void)//清空缓存
{
    buf_uart2.index=0;
	  buf_uart2.rx_flag=0;
    memset(buf_uart2.buf,0,BUFLEN);
}

/*********************************串口2的服务函数*************************************************/
void USART2_Send_byte(char data)
{
	while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
	USART_SendData(USART2, data);
}




/*-------------------------------------------------*/
/*函数名:串口2 发送数组                             */
/*参  数:bound:波特率                             */
/*返回值:无                                        */
/*-------------------------------------------------*/
void USART2_Send(char *Data,uint16_t Len)
{ 
	uint16_t i;
	for(i=0; i<Len; i++)
	{
		USART2_Send_byte(Data[i]);
	}
}



void USART2_SendStr(char*SendBuf)//串口1打印数据
{
	while(*SendBuf)
	{
        while((USART2->SR&0X40)==0);//等待发送完成 
        USART2->DR = (u8) *SendBuf; 
        SendBuf++;
	}
}


void usart2_receive_process_event(unsigned char ch )     //串口2给4g用
{
    if(buf_uart2.index >= BUFLEN)
    {
        buf_uart2.index = 0 ;
    }
    else
    {
        buf_uart2.buf[buf_uart2.index++] = ch;
			
    }
}
void USART2_IRQHandler(void)                            //串口2接收函数
{
		char Res;
		Res=Res;
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断,可以扩展来控制
    {
        Res=USART_ReceiveData(USART2);//接收模块的数据;
        usart2_receive_process_event(Res);//接收模块的数据
    } 
    if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)  //模块空闲
    {
        Res=USART_ReceiveData(USART2);//接收模块的数据;
        buf_uart2.rx_flag=1;
		 } 
}


#endif


#if EN_USART3

UART_BUF buf_uart3;     //TTL
void usart3_init(u32 bound)
{
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
		USART_InitTypeDef USART_InitStructure;
		NVIC_InitTypeDef NVIC_InitStructure;
		 
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能,GPIOA时钟
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//USART3
		USART_DeInit(USART3);  //复位串口3
	 //USART3_TX   PB10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
    GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PA2
   
    //USART3_RX	  PB11
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PB11

  
   //USART 初始化设置

		USART_InitStructure.USART_BaudRate = bound;//115200
		USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
		USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
		USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
		USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
		USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
    USART_Init(USART3, &USART_InitStructure); //初始化串口
	
    USART_Cmd(USART3, ENABLE);                    //使能串口 

#if EN_USART3_RX	

	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启相关中断
	USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);//开启相关中断
	USART_ClearFlag(USART3, USART_FLAG_TC);
	//Usart3 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;//串口3中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、
#endif
	
}


void USART3_Send_byte(char data)
{
	while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
	USART_SendData(USART3, data);
}


/*-------------------------------------------------*/
/*函数名:串口2 发送数组                             */
/*参  数:bound:波特率                             */
/*返回值:无                                        */
/*-------------------------------------------------*/
void USART3_Send(char *Data,uint16_t Len)
{ 
	uint16_t i;
	for(i=0; i<Len; i++)
	{
		USART3_Send_byte(Data[i]);
	}
}




void USART3_SendStr(char*SendBuf)//串口3打印数据
{
	while(*SendBuf)
	{
        while((USART3->SR&0X40)==0);//等待发送完成 
        USART3->DR = (u8) *SendBuf; 
        SendBuf++;
	}
}


/*****************************************************
清空电脑反馈的缓冲数据 串口1
*****************************************************/
void Clear_Buffer_UART3(void)//清空缓存
{
    buf_uart3.index=0;
	  buf_uart3.rx_flag=0;
    memset(buf_uart3.buf,0,BUFLEN);
}
void USART3_receive_process_event(char ch )     //串口2给4g用
{
    if(buf_uart3.index >= BUFLEN)
    {
        buf_uart3.index = 0 ;
    }
    else
    {
        buf_uart3.buf[buf_uart3.index++] = ch;
    }
} 
void USART3_IRQHandler(void)                                //串口3中断服务程序
{
		char Res;
		Res=Res;
    if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //接收中断,可以扩展来控制
    {
        Res=USART_ReceiveData(USART3);//接收模块的数据;
        USART3_receive_process_event(Res);
    } 
    if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)  //模块空闲
    {
        Res=USART_ReceiveData(USART3);//接收模块的数据;
				buf_uart3.rx_flag=1;
    } 
} 	

#endif




RC522.c

// Mifare RC522 RFID Card reader 13.56 MHz
// MFRC522		STM32F103		DESCRIPTION
// CS (SDA)		PB0				SPI1_NSS	Chip select for SPI
// SCK			PA5				SPI1_SCK	Serial Clock for SPI
// MOSI			PA7 			SPI1_MOSI	Master In Slave Out for SPI
// MISO			PA6				SPI1_MISO	Master Out Slave In for SPI
// IRQ			-				Irq
// GND			GND				Ground
// RST			3.3V			Reset pin (3.3V)
// VCC			3.3V			3.3V power
#include "RC522.h"
#include "SPI.h"

#include "bsp_usart.h"
#include "stm32f10x.h"  
#include "string.h"  
#include "stdio.h" 
#include "delay.h"  
extern uint8_t cardID[4];
/******template******/
// 0-255数字转换为字符  0xFF--"FF"
void char_to_hex(uint8_t data, uint8_t *retStr) {
	uint8_t digits[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
	
	if (data < 16) {
		retStr[0] = '0';
		retStr[1] = digits[data];
	} else {
		retStr[0] = digits[(data & 0xF0)>>4];
		retStr[1] = digits[(data & 0x0F)];
	}
}
/**
  * @brief  扫描RFID卡
  * @param  cardID 四字节数组
  * @retval 0扫描到RFID卡
  */
uint8_t RC522_cardScan(uint8_t *cardID)
{
	if(!MFRC522_Request(PICC_REQIDL, cardID)) {
		if(!MFRC522_Anticoll(cardID)) {
			
#ifdef DEBUG_printf
			uint8_t cardIDString[8] = {0};
			for(uint8_t i = 0; i < 4; i++) {
				char_to_hex(cardID[i], cardIDString+i*2);
			}
			printf("card id:%s\n", cardIDString);
#endif
			return 0;
		}
	}
	return 1;
}
/********************/


void SPI1_WriteReg(uint8_t address, uint8_t value) {
	cs_reset();
	SPISendByte(address);
	SPISendByte(value);
	cs_set();
}

uint8_t SPI1_ReadReg(uint8_t address) {
	uint8_t	val;

	cs_reset();
	SPISendByte(address);
	val = SPISendByte(0x00);
	cs_set();
	return val;
}

void MFRC522_WriteRegister(uint8_t addr, uint8_t val) {
	addr = (addr << 1) & 0x7E;															// Address format: 0XXXXXX0
  SPI1_WriteReg(addr, val);
}

uint8_t MFRC522_ReadRegister(uint8_t addr) {
	uint8_t val;

	addr = ((addr << 1) & 0x7E) | 0x80;
	val = SPI1_ReadReg(addr);
	return val;	
}

uint8_t MFRC522_Check(uint8_t* id) {
	uint8_t status;
	status = MFRC522_Request(PICC_REQIDL, id);							// Find cards, return card type
	if (status == MI_OK) status = MFRC522_Anticoll(id);			// Card detected. Anti-collision, return card serial number 4 bytes
	MFRC522_Halt();																					// Command card into hibernation 
	return status;
}

uint8_t MFRC522_Compare(uint8_t* CardID, uint8_t* CompareID) {
	uint8_t i;
	for (i = 0; i < 5; i++) {
		if (CardID[i] != CompareID[i]) return MI_ERR;
	}
	return MI_OK;
}

void MFRC522_SetBitMask(uint8_t reg, uint8_t mask) {
	MFRC522_WriteRegister(reg, MFRC522_ReadRegister(reg) | mask);
}

void MFRC522_ClearBitMask(uint8_t reg, uint8_t mask){
	MFRC522_WriteRegister(reg, MFRC522_ReadRegister(reg) & (~mask));
}

uint8_t MFRC522_Request(uint8_t reqMode, uint8_t* TagType) {
	uint8_t status;  
	uint16_t backBits;																			// The received data bits

	MFRC522_WriteRegister(MFRC522_REG_BIT_FRAMING, 0x07);		// TxLastBists = BitFramingReg[2..0]
	TagType[0] = reqMode;
	status = MFRC522_ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits);
	if ((status != MI_OK) || (backBits != 0x10)) status = MI_ERR;
	return status;
}

uint8_t MFRC522_ToCard(uint8_t command, uint8_t* sendData, uint8_t sendLen, uint8_t* backData, uint16_t* backLen) {
	uint8_t status = MI_ERR;
	uint8_t irqEn = 0x00;
	uint8_t waitIRq = 0x00;
	uint8_t lastBits;
	uint8_t n;
	uint16_t i;

	switch (command) {
		case PCD_AUTHENT: {
			irqEn = 0x12;
			waitIRq = 0x10;
			break;
		}
		case PCD_TRANSCEIVE: {
			irqEn = 0x77;
			waitIRq = 0x30;
			break;
		}
		default:
		break;
	}

	MFRC522_WriteRegister(MFRC522_REG_COMM_IE_N, irqEn | 0x80);
	MFRC522_ClearBitMask(MFRC522_REG_COMM_IRQ, 0x80);
	MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80);
	MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_IDLE);

	// Writing data to the FIFO
	for (i = 0; i < sendLen; i++) MFRC522_WriteRegister(MFRC522_REG_FIFO_DATA, sendData[i]);

	// Execute the command
	MFRC522_WriteRegister(MFRC522_REG_COMMAND, command);
	if (command == PCD_TRANSCEIVE) MFRC522_SetBitMask(MFRC522_REG_BIT_FRAMING, 0x80);		// StartSend=1,transmission of data starts 

	// Waiting to receive data to complete
	i = 2000;	// i according to the clock frequency adjustment, the operator M1 card maximum waiting time 25ms
	do {
		// CommIrqReg[7..0]
		// Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
		n = MFRC522_ReadRegister(MFRC522_REG_COMM_IRQ);
		i--;
	} while ((i!=0) && !(n&0x01) && !(n&waitIRq));

	MFRC522_ClearBitMask(MFRC522_REG_BIT_FRAMING, 0x80);																// StartSend=0

	if (i != 0)  {
		if (!(MFRC522_ReadRegister(MFRC522_REG_ERROR) & 0x1B)) {
			status = MI_OK;
			if (n & irqEn & 0x01) status = MI_NOTAGERR;
			if (command == PCD_TRANSCEIVE) {
				n = MFRC522_ReadRegister(MFRC522_REG_FIFO_LEVEL);
				lastBits = MFRC522_ReadRegister(MFRC522_REG_CONTROL) & 0x07;
				if (lastBits) *backLen = (n-1)*8+lastBits; else *backLen = n*8;
				if (n == 0) n = 1;
				if (n > MFRC522_MAX_LEN) n = MFRC522_MAX_LEN;
				for (i = 0; i < n; i++) backData[i] = MFRC522_ReadRegister(MFRC522_REG_FIFO_DATA);		// Reading the received data in FIFO
			}
		} else status = MI_ERR;
	}
	return status;
}

uint8_t MFRC522_Anticoll(uint8_t* serNum) {
	uint8_t status;
	uint8_t i;
	uint8_t serNumCheck = 0;
	uint16_t unLen;

	MFRC522_WriteRegister(MFRC522_REG_BIT_FRAMING, 0x00);												// TxLastBists = BitFramingReg[2..0]
	serNum[0] = PICC_ANTICOLL;
	serNum[1] = 0x20;
	status = MFRC522_ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen);
	if (status == MI_OK) {
		// Check card serial number
		for (i = 0; i < 4; i++) serNumCheck ^= serNum[i];
		if (serNumCheck != serNum[i]) status = MI_ERR;
	}
	return status;
} 

void MFRC522_CalculateCRC(uint8_t*  pIndata, uint8_t len, uint8_t* pOutData) {
	uint8_t i, n;

	MFRC522_ClearBitMask(MFRC522_REG_DIV_IRQ, 0x04);													// CRCIrq = 0
	MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80);													// Clear the FIFO pointer
	// Write_MFRC522(CommandReg, PCD_IDLE);

	// Writing data to the FIFO	
	for (i = 0; i < len; i++) MFRC522_WriteRegister(MFRC522_REG_FIFO_DATA, *(pIndata+i));
	MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_CALCCRC);

	// Wait CRC calculation is complete
	i = 0xFF;
	do {
		n = MFRC522_ReadRegister(MFRC522_REG_DIV_IRQ);
		i--;
	} while ((i!=0) && !(n&0x04));																						// CRCIrq = 1

	// Read CRC calculation result
	pOutData[0] = MFRC522_ReadRegister(MFRC522_REG_CRC_RESULT_L);
	pOutData[1] = MFRC522_ReadRegister(MFRC522_REG_CRC_RESULT_M);
}

uint8_t MFRC522_SelectTag(uint8_t* serNum) {
	uint8_t i;
	uint8_t status;
	uint8_t size;
	uint16_t recvBits;
	uint8_t buffer[9]; 

	buffer[0] = PICC_SElECTTAG;
	buffer[1] = 0x70;
	for (i = 0; i < 5; i++) buffer[i+2] = *(serNum+i);
	MFRC522_CalculateCRC(buffer, 7, &buffer[7]);		//??
	status = MFRC522_ToCard(PCD_TRANSCEIVE, buffer, 9, buffer, &recvBits);
	if ((status == MI_OK) && (recvBits == 0x18)) size = buffer[0]; else size = 0;
	return size;
}

uint8_t MFRC522_Auth(uint8_t authMode, uint8_t BlockAddr, uint8_t* Sectorkey, uint8_t* serNum) {
	uint8_t status;
	uint16_t recvBits;
	uint8_t i;
	uint8_t buff[12]; 

	// Verify the command block address + sector + password + card serial number
	buff[0] = authMode;
	buff[1] = BlockAddr;
	for (i = 0; i < 6; i++) buff[i+2] = *(Sectorkey+i);
	for (i=0; i<4; i++) buff[i+8] = *(serNum+i);
	status = MFRC522_ToCard(PCD_AUTHENT, buff, 12, buff, &recvBits);
	if ((status != MI_OK) || (!(MFRC522_ReadRegister(MFRC522_REG_STATUS2) & 0x08))) status = MI_ERR;
	return status;
}

uint8_t MFRC522_Read(uint8_t blockAddr, uint8_t* recvData) {
	uint8_t status;
	uint16_t unLen;

	recvData[0] = PICC_READ;
	recvData[1] = blockAddr;
	MFRC522_CalculateCRC(recvData,2, &recvData[2]);
	status = MFRC522_ToCard(PCD_TRANSCEIVE, recvData, 4, recvData, &unLen);
	if ((status != MI_OK) || (unLen != 0x90)) status = MI_ERR;
	return status;
}

uint8_t MFRC522_Write(uint8_t blockAddr, uint8_t* writeData) {
	uint8_t status;
	uint16_t recvBits;
	uint8_t i;
	uint8_t buff[18]; 

	buff[0] = PICC_WRITE;
	buff[1] = blockAddr;
	MFRC522_CalculateCRC(buff, 2, &buff[2]);
	status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &recvBits);
	if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)) status = MI_ERR;
	if (status == MI_OK) {
		// Data to the FIFO write 16Byte
		for (i = 0; i < 16; i++) buff[i] = *(writeData+i);
		MFRC522_CalculateCRC(buff, 16, &buff[16]);
		status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 18, buff, &recvBits);
		if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)) status = MI_ERR;
	}
	return status;
}

void MFRC522_Init(void) {
	MFRC522_Reset();
	MFRC522_WriteRegister(MFRC522_REG_T_MODE, 0x8D);
	MFRC522_WriteRegister(MFRC522_REG_T_PRESCALER, 0x3E);
	MFRC522_WriteRegister(MFRC522_REG_T_RELOAD_L, 30);           
	MFRC522_WriteRegister(MFRC522_REG_T_RELOAD_H, 0);
	MFRC522_WriteRegister(MFRC522_REG_RF_CFG, 0x70);				// 48dB gain	
	MFRC522_WriteRegister(MFRC522_REG_TX_AUTO, 0x40);
	MFRC522_WriteRegister(MFRC522_REG_MODE, 0x3D);
	MFRC522_AntennaOn();																		// Open the antenna
}

void MFRC522_Reset(void) {
	MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_RESETPHASE);
}

void MFRC522_AntennaOn(void) {
	uint8_t temp;

	temp = MFRC522_ReadRegister(MFRC522_REG_TX_CONTROL);
	if (!(temp & 0x03)) MFRC522_SetBitMask(MFRC522_REG_TX_CONTROL, 0x03);
}

void MFRC522_AntennaOff(void) {
	MFRC522_ClearBitMask(MFRC522_REG_TX_CONTROL, 0x03);
}

void MFRC522_Halt(void) {
	uint16_t unLen;
	uint8_t buff[4]; 

	buff[0] = PICC_HALT;
	buff[1] = 0;
	MFRC522_CalculateCRC(buff, 2, &buff[2]);
	MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &unLen);
}

8.实现效果图片:

代码链接:STM32F103C8T6RFIDNFC模块的刷卡感应和代码驱动资源-CSDN下载

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐