STM32F103C8T6 RFID NFC模块的刷卡感应和代码驱动
RFID(RadioFrequencyIdentification,射频识别技术)是一种非接触式的自动识别技术,通过射频信号自动识别目标对象并获取相关数据,广泛应用于物流、零售、交通、医疗等多个领域。以下从技术原理、组成部分、应用场景及优缺点等方面详细介绍:1、RFID技术的基本原理RFID技术利用无线电波进行数据传输和通信,其核心原理是电磁感应或电磁反向散射耦合。
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.实现效果图片:

更多推荐





所有评论(0)