给机器人加个刷卡开门、刷卡签到的功能,最容易上手的就是 RC522 这块蓝色小板。它工作在 13.56MHz,基于 NXP 的 MFRC522 芯片,配套的 MIFARE Classic 卡和钥匙扣网上十几块钱一大把,接 ESP32 只要七根杜邦线就能读出卡号。这篇把它一次讲透:引脚怎么认、怎么接、库怎么装、代码逐行干什么,以及几个新手最容易栽的坑。

先认清这 8 个引脚
RC522 模块一共 8 根引脚,其中几根是三个通信接口共用的:它支持 SPI、I2C、UART 三种模式,同一时刻只能用一种。玩 ESP32 基本都走 SPI,速度最快、资料也最多。把每根脚先认清楚:
- GND:接地,与 ESP32 共地
- VCC:接 3.3V,模块是 3.3V 器件,接 5V 会烧
- RST:复位与掉电控制,拉低进入硬掉电,上升沿复位模块
- IRQ:中断输出,卡片进入感应区时可提醒主控,本篇不接
- MISO/SCL/TX:SPI 模式下是 MISO,I2C 模式下是 SCL,UART 模式下是 TX
- MOSI:SPI 主出从入
- SCK:SPI 时钟
- SS/SDA/RX:SPI 模式下是片选 SS,注意它不是 I2C 的 SDA

特别提醒一句:板子上印的 SDA 在 SPI 模式里是片选信号,很多人第一眼以为要接 I2C 总线,方向就带偏了。引脚丝印在不同厂商的小板上顺序可能不一样,接线前认字,别认记忆里的位置。
接线表:七根线搞定
ESP32 是 3.3V 逻辑,与 RC522 电平直接兼容,不需要电平转换。对照官方教程的接线图和接线表,一根一根接:
| RC522 引脚 | ESP32 引脚 | 说明 |
|---|---|---|
| VCC | 3.3V | 严禁接 5V/VIN |
| GND | GND | 共地 |
| SCK | GPIO18 | SPI 时钟 |
| MOSI | GPIO23 | 主出从入 |
| MISO | GPIO19 | 主入从出 |
| SS/SDA | GPIO5 | SPI 片选 |
| RST | GPIO27 | 复位 |
| IRQ | 不接 | 本篇用轮询方式 |
SS 和 RST 用哪两个 GPIO 其实不强制:GPIO5、GPIO27 是常见选择,别的教程里也有用 GPIO21/22 或 GPIO26 的,只要和代码里的 define 对得上就行。建议杜邦线尽量短,读卡距离本来就只有几厘米,接触不良时故障会非常迷惑。另外别把模块贴在大金属面上工作,金属会明显压缩本来就短的感应距离。
装库:认准 GithubCommunity 的 MFRC522
Arduino IDE 左侧点 Libraries 图标,搜索框输入 MFRC522,选 GithubCommunity 发布的那个安装,我这边看到的是 1.4.11 版。库里同名甚至近名的库不止一个,API 对不上是新手最常见的问题,装错库后面每一行代码都会报错。

如果你的板子还没配好 ESP32 环境,先在开发板管理器里装好 ESP32 支持包,板型选 ESP32 Dev Module,再往下走。
示例代码:读出卡类型和 UID
下面这份示例代码机械照搬自库文档与教程原帖,一个字符没改,功能是刷任何卡都会在串口打印卡片类型和十六进制 UID。按平台兼容要求,头文件用了双引号写法,与尖括号写法在编译上等价:
#include "SPI.h"
#include "MFRC522.h"
#define SS_PIN 5 // ESP32 pin GPIO5
#define RST_PIN 27 // ESP32 pin GPIO27
MFRC522 rfid(SS_PIN, RST_PIN);
void setup() {
Serial.begin(9600);
SPI.begin(); // init SPI bus
rfid.PCD_Init(); // init MFRC522
Serial.println("Tap an RFID/NFC tag on the RFID-RC522 reader");
}
void loop() {
if (rfid.PICC_IsNewCardPresent()) { // new tag is available
if (rfid.PICC_ReadCardSerial()) { // NUID has been readed
MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
Serial.print("RFID/NFC Tag Type: ");
Serial.println(rfid.PICC_GetTypeName(piccType));
// print UID in Serial Monitor in the hex format
Serial.print("UID:");
for (int i = 0; i < rfid.uid.size; i++) {
Serial.print(rfid.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(rfid.uid.uidByte[i], HEX);
}
Serial.println();
rfid.PICC_HaltA(); // halt PICC
rfid.PCD_StopCrypto1(); // stop encryption on PCD
}
}
}
上传后打开串口监视器,波特率设成 9600。把卡或钥匙扣平贴到天线附近,每刷一次会打印类似 MIFARE 1KB 的卡型,以及一串十六进制 UID,比如 13 9F 82 1A 这种格式。卡片拿开太快可能出现 Timeout in communication 提示,重新贴上即可。
三个最常见的坑
坑一:上电读不到,串口一直没反应。按顺序排查:3.3V 是否真的接到了 3V3 而不是 VIN;GND 是否共地;SS、RST 接的引脚与代码里 SS_PIN、RST_PIN 是否一致;SCK/MOSI/MISO 三根数据线有没有互相插串。先查接线再怀疑库,插着的上传成功只说明程序进板了,不代表读卡器通了。
坑二:有的卡读得出,有的读不出。这不一定是坏了。RC522 只支持 13.56MHz 的 ISO14443A 类卡,像 MIFARE Classic、MIFARE Ultralight 可以读;你口袋里的银行卡、交通卡有些是别的协议或加密卡,可能读不出 UID 或读出的类型对不上。刷不出来先换套件里配的空白卡测试。也别拿别人的卡去乱刷,读到 UID 不等于有权操作别人的卡。
坑三:UID 当密码用。库文档里明确写过,仅靠 UID 做门禁认证并不安全,MIFARE Classic 的 Crypto1 加密早已被公开破解,UID 可以被克隆。自己做玩具、签到、点名没问题;真要做门禁,UID 只能当一层,后端校验、加密认证都得另外设计。
刷完卡号,下一步能玩什么
读 UID 只是第一步。后续可以把 UID 存进数组做白名单比对,控制继电器或舵机模拟开门;也可以配合 OLED 屏显示刷卡结果。扩展时记得 SS 占了 GPIO5、RST 占了 GPIO27,再挂 I2C 屏幕用 21/22 不冲突,挂别的 SPI 设备则要另外分配片选脚,避免和 GPIO5 打架。
十几块钱给机器人加一个身份识别入口,这块小板的性价比确实没得说。先把 UID 稳定读出来,再一层一层往上加功能,每加一层都单测一遍,比一上来就堆大工程靠谱得多。


上面那条手滑打串字了,重说:装库一定认准 GithubCommunity 那个,我当初装错成另一个同名库,API 全对不上,编译报错报到怀疑人生。
suggestive提示:库一定认准 GithubCommunity 那个,我装错成另一个同名库,编译报错报到我怀疑人生。
照这个接了一遍,卡号一次就出来了。补一句,30 脚的窄板 GPIO27 也能用,但有些板子丝印只写 D27,别找错位置。
SDA 那个坑真的经典,我第一次玩的时候真给它接 I2C 总线上去了,折腾了一晚上才发现是片选。
问下大佬,MIFARE Ultralight 的卡也能这样读 UID 吗?手里有几张地铁卡样子的卡一直读不出来。