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
MFRC522 库
Section titled “MFRC522 库”Miguel Balboa 的 MFRC522 库是 RC522 RFID 模块最广泛使用的 Arduino 库。它提供:
- 完整的 SPI 通信处理
- 标签检测和 UID 读取
- MIFARE 卡读写操作
- 用于常见操作的内置辅助函数
库详情:
| 属性 | 值 |
|---|---|
| 库名称 | MFRC522 |
| 作者 | Miguel Balboa |
| 仓库 | GitHub - miguelbalboa/MFRC522 |
| 许可协议 | LGPL-2.1 |
| 最近更新 | 2024(持续维护中) |
SPI 通信概述
Section titled “SPI 通信概述”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 进行通信)
步骤 1:安装 MFRC522 库
Section titled “步骤 1:安装 MFRC522 库”PlatformIO 方法:
在 platformio.ini 中添加:
[env:esp32dev]platform = espressif32board = esp32devframework = arduinolib_deps = miguelbalboa/MFRC522 @ ^1.4.11 pubsubclientArduino IDE 方法:
草稿 → 包含库 → 管理库搜索:"MFRC522" 作者 Miguel Balboa点击"安装"(版本 1.4.11 或更高)步骤 2:包含库并定义引脚
Section titled “步骤 2:包含库并定义引脚”创建一个包含 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) ← 或类似的版本号⚠️ 重要提示:如果固件版本返回 0x00 或 0xFF,则 SPI 接线不正确或模块未响应。
步骤 4:完整验证草稿
Section titled “步骤 4:完整验证草稿”以下是一个验证 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); // 避免重复读取同一标签 }}库 API 参考
Section titled “库 API 参考”MFRC522 关键函数
Section titled “MFRC522 关键函数”| 函数 | 描述 | 使用时机 |
|---|---|---|
PCD_Init() | 初始化 RC522 模块 | 在 setup() 中调用一次 |
PICC_IsNewCardPresent() | 检查读取器附近是否有新标签 | 在 loop() 中,读取前调用 |
PICC_ReadCardSerial() | 读取标签的 UID | 在 PICC_IsNewCardPresent() 返回 true 后调用 |
PICC_HaltA() | 停止与当前标签的通信 | 读取 UID 后调用 |
PCD_StopCrypto1() | 停止 PCD 上的加密 | 读/写操作后调用 |
PCD_DumpVersionToSerial() | 将固件版本打印到串口 | 用于调试/验证 |
PCD_SetAntennaGain() | 调整天线灵敏度 | 增加或减少读取距离 |
UID 数据结构
Section titled “UID 数据结构”// 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物理测试:
- 打开串口监视器(115200 波特率)
- 将 RFID 标签靠近 RC522 天线(约 3cm)
- 观察串口监视器中打印的 UID
- 每次检测到标签时绿色 LED 应短暂闪烁
- 用多个标签测试以验证不同的 UID
问题 1:无固件版本
Section titled “问题 1:无固件版本”症状:串口显示 固件版本:0x00 或 0xFF
原因:
- 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)
- 天线损坏
解决方案:
- 验证标签类型(应标明”13.56 MHz”或”MIFARE”)
- 将标签放得极近(几乎触碰天线)
- 检查 RC522 上的天线线圈是否有明显损坏
问题 3:同一标签多次触发
Section titled “问题 3:同一标签多次触发”症状:保持标签静止会导致连续重复读取
解决方案:添加延迟和检测状态:
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 线,这可能导致通信错误
- 库:使用 Miguel Balboa 的 MFRC522——RC522 的标准 Arduino 库
- 初始化:启动 SPI 总线,然后调用
PCD_Init()——始终验证固件版本 - 检测:在循环中使用
PICC_IsNewCardPresent()+PICC_ReadCardSerial() - UID 格式:4 字节或 7 字节标识符,通过
rfid.uid.uidByte[]访问 - 调试:固件版本
0x00或0xFF表示接线问题