STM32 驱动 RC522(MFRC522)实现方案 适用于 STM32F1/F4/G0/L4 等全系列(HAL 库),实现 RFID 卡号读取(Mifare Classic)。
一、硬件连接(SPI 方式,最常用 )
RC522 支持 SPI / I2C / UART ,STM32 一般用 SPI(最快最稳)。
1、推荐接线(STM32 ↔ RC522)
| RC522 | STM32 | 说明 |
|---|---|---|
| VCC | 3.3V | ❗❗ 严禁 5V |
| GND | GND | |
| RST | PB0 | 复位 |
| NSS / SDA | PB12 | SPI 片选 |
| SCK | PB13 | SPI 时钟 |
| MOSI | PB15 | SPI 输出 |
| MISO | PB14 | SPI 输入 |
| IRQ | NC | 中断(可选) |
推荐 SPI 速率:≤ 10MHz
SPI 模式:Mode 0 (CPOL=0, CPHA=0)
二、SPI & GPIO 初始化(CubeMX)
SPI 配置
| 参数 | 值 |
|---|---|
| Mode | Full-Duplex Master |
| Frame Format | Motorola |
| Data Size | 8 bits |
| CPOL | Low |
| CPHA | 1 Edge |
| Prescaler | 8 ~ 16 |
| NSS | Soft |
GPIO
| 引脚 | 模式 |
|---|---|
| PB12 | GPIO_Output(CS) |
| PB0 | GPIO_Output(RST) |
三、RC522 驱动核心代码
1、 rc522.h
c
#ifndef __RC522_H
#define __RC522_H
#include "stm32f4xx_hal.h"
#define RC522_CS_LOW() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET)
#define RC522_CS_HIGH() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET)
#define RC522_RST_LOW() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET)
#define RC522_RST_HIGH() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET)
void RC522_Init(void);
uint8_t RC522_Request(uint8_t req_code, uint8_t *card_type);
uint8_t RC522_Anticoll(uint8_t *uid);
uint8_t RC522_SelectTag(uint8_t *uid);
uint8_t RC522_Auth(uint8_t auth_mode, uint8_t block, uint8_t *key, uint8_t *uid);
uint8_t RC522_Read(uint8_t block, uint8_t *data);
uint8_t RC522_Write(uint8_t block, uint8_t *data);
#endif
2、rc522.c(核心)
SPI 读写
c
#include "rc522.h"
#include "spi.h"
static uint8_t RC522_ReadByte(uint8_t addr)
{
uint8_t tx = 0x80 | (addr << 1);
uint8_t rx = 0;
RC522_CS_LOW();
HAL_SPI_TransmitReceive(&hspi2, &tx, &rx, 1, 10);
HAL_SPI_Receive(&hspi2, &rx, 1, 10);
RC522_CS_HIGH();
return rx;
}
static void RC522_WriteByte(uint8_t addr, uint8_t val)
{
uint8_t tx[2] = {(addr << 1), val};
RC522_CS_LOW();
HAL_SPI_Transmit(&hspi2, tx, 2, 10);
RC522_CS_HIGH();
}
RC522 初始化
c
void RC522_Init(void)
{
RC522_RST_HIGH();
HAL_Delay(50);
RC522_WriteByte(0x01, 0x0F); // Command = SoftReset
RC522_WriteByte(0x2A, 0x8D); // TAuto=1
RC522_WriteByte(0x2B, 0x3E); // TPreScaler
RC522_WriteByte(0x2D, 30); // TReloadVal
RC522_WriteByte(0x2C, 0);
RC522_WriteByte(0x15, 0x40); // Force100ASK
RC522_WriteByte(0x11, 0x3D); // Mode
RC522_WriteByte(0x26, 0x60); // TxControl (ANT=ON)
}
寻卡(REQA)
c
uint8_t RC522_Request(uint8_t req, uint8_t *card_type)
{
uint8_t status;
RC522_WriteByte(0x01, 0x0C); // Idle
RC522_WriteByte(0x0D, 0x07); // BitFraming
RC522_WriteByte(0x1C, req);
card_type[0] = RC522_ReadByte(0x22);
card_type[1] = RC522_ReadByte(0x21);
return 0;
}
防冲突 & 读 UID
c
uint8_t RC522_Anticoll(uint8_t *uid)
{
RC522_WriteByte(0x01, 0x0C);
RC522_WriteByte(0x0D, 0x00);
RC522_WriteByte(0x1C, 0x93);
for (int i = 0; i < 5; i++)
uid[i] = RC522_ReadByte(0x22 + i);
return 0;
}
四、主函数示例(读取卡号)
c
uint8_t uid[5];
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_SPI2_Init();
MX_GPIO_Init();
RC522_Init();
while (1)
{
if (RC522_Request(0x26, uid) == 0)
{
if (RC522_Anticoll(uid) == 0)
{
printf("Card UID: %02X %02X %02X %02X\r\n",
uid[0], uid[1], uid[2], uid[3]);
}
}
HAL_Delay(500);
}
}
参考代码 基于STM32 驱动RC522 读RFID程序 www.youwenfan.com/contentcst/182345.html
五、常见卡类型对照
| 返回值 | 卡类型 |
|---|---|
| 0x0400 | Mifare UltraLight |
| 0x0200 | Mifare Classic 1K |
| 0x0800 | Mifare Classic 4K |
六、调试指南
| 问题 | 原因 |
|---|---|
| 读不到卡 | 天线未打开 / 电压不稳 |
| SPI 无响应 | CS 没拉低 / SPI 模式错 |
| UID 变化 | 电磁干扰 / 供电不足 |
| 只能读一次 | 未复位 CommandReg |