跳转到内容

RC522模块集成

RC522模块集成

本节介绍 MFRC522 库与 ESP32 的软件集成,包括库安装、SPI 初始化和基本通信验证。学习完本节后,您将能够:

  • 为 Arduino/PlatformIO 安装 MFRC522 库
  • 在 ESP32 代码中通过 SPI 初始化 RC522 模块
  • 验证 ESP32 和 RC522 之间的通信
  • 了解库的对象模型和关键函数

开始本节前,请确保您已完成:

  • 05-02 完成硬件接线
  • 设置好 Arduino IDE 或 PlatformIO IDE(参见第 01 章)
  • 来自第 01 章的基础草图模板(WiFi + MQTT)
  • RC522 模块已正确连接到 ESP32

Miguel Balboa 的 MFRC522 库是 RC522 RFID 模块最广泛使用的 Arduino 库。它提供:

  • 完整的 SPI 通信处理
  • 标签检测和 UID 读取
  • MIFARE 卡读写操作
  • 用于常见操作的内置辅助函数

库详情

属性
库名称MFRC522
作者Miguel Balboa
仓库GitHub - miguelbalboa/MFRC522
许可协议LGPL-2.1
最近更新2024(持续维护中)

ESP32 通过 SPI(串行外设接口)总线与 RC522 通信:

SPI 通信路径:
┌─────────┐ ┌─────────┐
│ ESP32 │ │ RC522 │
│ │ MOSI (GPIO 23)──→│ │
│ 主设备 │←──MISO (GPIO 19) │ 从设备 │
│ │ SCK (GPIO 18)──→│ │
│ │ SS (GPIO 5)───→│ │
└─────────┘ └─────────┘
  • MOSI:主出从入(ESP32 向 RC522 发送命令)
  • MISO:主入从出(RC522 向 ESP32 响应)
  • SCK:串行时钟(同步数据传输)
  • SS:从设备选择(选择 RC522 进行通信)

PlatformIO 方法

platformio.ini 中添加:

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
miguelbalboa/MFRC522 @ ^1.4.11
pubsubclient

Arduino IDE 方法

草稿 → 包含库 → 管理库
搜索:"MFRC522" 作者 Miguel Balboa
点击"安装"(版本 1.4.11 或更高)

创建一个包含 MFRC522 库的新草稿:

#include <SPI.h>
#include <MFRC522.h>
// RC522 引脚定义
#define RST_PIN 4 // 复位引脚
#define SS_PIN 5 // 从设备选择(SDA)引脚
// 创建 MFRC522 实例
MFRC522 rfid(SS_PIN, RST_PIN);
// LED 引脚定义
#define LED_GREEN 22
#define LED_RED 21

代码说明

  • SS_PIN(GPIO 5)与步骤 2 中的 SDA/SS 线匹配
  • RST_PIN(GPIO 4)是模块的硬件复位
  • MFRC522 对象使用这两个引脚实例化
  • LED 引脚定义为视觉反馈(稍后使用)

步骤 3:在 Setup 中初始化 SPI 和 RC522

Section titled “步骤 3:在 Setup 中初始化 SPI 和 RC522”
void setup() {
Serial.begin(115200);
// 初始化 LED 引脚
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_RED, OUTPUT);
// 初始化 SPI 总线
SPI.begin(); // SCK=18, MOSI=23, MISO=19(ESP32 默认)
// 初始化 MFRC522
rfid.PCD_Init();
// 验证模块是否响应
rfid.PCD_DumpVersionToSerial();
Serial.println("RFID 读取器就绪。");
// 初始 LED 测试
digitalWrite(LED_GREEN, HIGH);
delay(500);
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_RED, HIGH);
delay(500);
digitalWrite(LED_RED, LOW);
}

预期的串口输出

RFID 读取器就绪。
固件版本:0x92 (2.0) ← 或类似的版本号

⚠️ 重要提示:如果固件版本返回 0x000xFF,则 SPI 接线不正确或模块未响应。

以下是一个验证 RC522 通信的完整最小草稿:

#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 4
#define SS_PIN 5
MFRC522 rfid(SS_PIN, RST_PIN);
#define LED_GREEN 22
#define LED_RED 21
void setup() {
Serial.begin(115200);
while (!Serial); // 等待串口(仅限 Leonardo/Micro)
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_RED, OUTPUT);
SPI.begin(); // 初始化 SPI
rfid.PCD_Init(); // 初始化 RFID
Serial.print("RFID 固件版本:0x");
Serial.println(rfid.PCD_ReadRegister(MFRC522::VersionReg), HEX);
if (rfid.PCD_ReadRegister(MFRC522::VersionReg) == 0x00 ||
rfid.PCD_ReadRegister(MFRC522::VersionReg) == 0xFF) {
Serial.println("错误:RFID 模块未响应!");
digitalWrite(LED_RED, HIGH); // 红灯 = 错误
while (1); // 停止
}
Serial.println("RFID 读取器就绪。");
digitalWrite(LED_GREEN, HIGH); // 绿灯 = 就绪
}
void loop() {
// 检查新的 RFID 标签
if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
Serial.print("检测到标签!UID:");
String uid = "";
for (byte i = 0; i < rfid.uid.size; i++) {
uid += String(rfid.uid.uidByte[i], HEX);
}
uid.toUpperCase();
Serial.println(uid);
// 检测到标签时绿灯闪烁
digitalWrite(LED_GREEN, LOW);
delay(100);
digitalWrite(LED_GREEN, HIGH);
// 停止 PICC 通信并结束加密
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
delay(1000); // 避免重复读取同一标签
}
}
函数描述使用时机
PCD_Init()初始化 RC522 模块setup() 中调用一次
PICC_IsNewCardPresent()检查读取器附近是否有新标签loop() 中,读取前调用
PICC_ReadCardSerial()读取标签的 UIDPICC_IsNewCardPresent() 返回 true 后调用
PICC_HaltA()停止与当前标签的通信读取 UID 后调用
PCD_StopCrypto1()停止 PCD 上的加密读/写操作后调用
PCD_DumpVersionToSerial()将固件版本打印到串口用于调试/验证
PCD_SetAntennaGain()调整天线灵敏度增加或减少读取距离
// rfid.uid 是一个包含以下内容的结构体:
struct MFRC522::Uid {
byte size; // UID 中的字节数(4 或 7)
byte uidByte[10]; // UID 字节
byte sak; // 选择确认字节
};
  • 4 字节 UID:标准 MIFARE Classic 标签
  • 7 字节 UID:新型标签的扩展 UID(NXP NTAG、MIFARE Ultralight)

上传验证草稿并进行测试:

// 预期的串口监视器输出:
// RFID 固件版本:0x92
// RFID 读取器就绪。
// 检测到标签!UID:04A3B2C1
// 检测到标签!UID:E5F81234

物理测试

  1. 打开串口监视器(115200 波特率)
  2. 将 RFID 标签靠近 RC522 天线(约 3cm)
  3. 观察串口监视器中打印的 UID
  4. 每次检测到标签时绿色 LED 应短暂闪烁
  5. 用多个标签测试以验证不同的 UID

症状:串口显示 固件版本:0x000xFF

原因

  • SPI 接线不正确
  • 模块未通电
  • 模块损坏

解决方案

// 检查每个 SPI 连接:
// 1. 用万用表验证 RC522 VCC 引脚上的 3.3V
// 2. 验证 ESP32 和 RC522 之间的 GND 导通
// 3. 如果使用非标准引脚分配,交换 MOSI 和 MISO
// 4. 尝试使用不同的 RC522 模块

问题 2:“PICC_IsNewCardPresent” 始终返回 false

Section titled “问题 2:“PICC_IsNewCardPresent” 始终返回 false”

症状:永远检测不到标签

原因

  • 标签不是 13.56 MHz(例如使用了 125 kHz 标签)
  • 读取距离太远(> 5cm)
  • 天线损坏

解决方案

  1. 验证标签类型(应标明”13.56 MHz”或”MIFARE”)
  2. 将标签放得极近(几乎触碰天线)
  3. 检查 RC522 上的天线线圈是否有明显损坏

症状:保持标签静止会导致连续重复读取

解决方案:添加延迟和检测状态:

bool tagRecentlyRead = false;
unsigned long lastReadTime = 0;
void loop() {
if (millis() - lastReadTime > 2000) { // 2 秒冷却时间
tagRecentlyRead = false;
}
if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
if (!tagRecentlyRead) {
// 处理标签
tagRecentlyRead = true;
lastReadTime = millis();
}
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
}
}
  • 建议:读取后始终调用 PICC_HaltA() 以防止连续重复读取
  • 建议:使用 PCD_SetAntennaGain(MFRC522::RxGain_max) 获得最大读取范围
  • 建议:启动时验证固件版本以尽早检测接线问题
  • 避免:以快于每秒 2-3 次的速度读取标签(可能导致 SPI 缓冲区溢出)
  • 避免:使用过长(> 30cm)的 SPI 线,这可能导致通信错误
  1. :使用 Miguel Balboa 的 MFRC522——RC522 的标准 Arduino 库
  2. 初始化:启动 SPI 总线,然后调用 PCD_Init()——始终验证固件版本
  3. 检测:在循环中使用 PICC_IsNewCardPresent() + PICC_ReadCardSerial()
  4. UID 格式:4 字节或 7 字节标识符,通过 rfid.uid.uidByte[] 访问
  5. 调试:固件版本 0x000xFF 表示接线问题