☰
ESP32与MFRC522实战:从零搭建RFID读卡系统
2026/10/8 6:38:01 网站建设 项目流程

1. 从零上手:为什么选ESP32加RFID这个组合

很多人第一次接触物联网硬件,都是从一块ESP32开发板开始的。它便宜、资料多、自带Wi-Fi和蓝牙,拿来做个小项目成就感来得特别快。但玩久了你会发现,光会点灯、读温湿度,总觉得少了点什么——设备只能“感知”环境,却没法“识别”人。而RFID无线射频卡这个东西,恰好补上了这块短板:刷一下卡,设备就知道“你是谁”,这一下子就把项目从玩具级别拉到了实用级别。

我最早做RFID项目,是为了给工作室做一个简单的门禁记录。当时试过好几种方案,最后发现ESP32加MFRC522模块是最省心的组合。MFRC522是一颗非常经典的13.56MHz非接触式读写芯片,支持ISO 14443A协议,市面上常见的M1卡、S50卡、UID卡它都能读。关键是这个模块便宜,十几块钱就能买到,配套的库也成熟,MicroPython和Arduino两边都有现成轮子,不用自己从寄存器开始啃。

这篇文章面向的是完全没有RFID基础的ESP32玩家。你不需要懂射频理论,也不需要会画电路板,只要你会给ESP32烧录程序、能看懂简单的接线图,就能跟着把整套东西跑起来。我会从硬件选型、接线、SPI通信原理,一路讲到代码实现、常见故障排查,最后再聊聊这个技术能延伸出哪些真正有用的项目。中间会穿插我自己踩过的坑,比如读卡距离忽远忽近、SPI片选搞错导致读不到卡、断电后程序不跑等等,这些都是文档里不会写、但实际做的时候一定会遇到的问题。

先把结论放前面:ESP32负责逻辑和联网,MFRC522负责射频识别,两者通过SPI总线通信。你只要把这三者的关系理顺,剩下的就是调参数和写业务逻辑的事。下面我按实际操作的顺序,一步步拆开讲。

2. 硬件选型与接线:别让一根线毁掉整个项目

2.1 MFRC522模块怎么挑

市面上MFRC522模块版本挺多,价格从几块到几十块都有。我建议优先选带3.3V稳压和电平转换的版本,因为ESP32的IO是3.3V逻辑,而有些便宜模块是5V供电的,直接接上去短时间可能能用,时间长了容易出问题。模块上一般有8个引脚:SDA(片选)、SCK(时钟)、MOSI(主出从入)、MISO(主入从出)、IRQ(中断)、GND、RST(复位)、3.3V(供电)。

这里有个特别容易搞混的点:MFRC522模块上标的SDA,其实就是SPI的CS(片选),不是I2C那个SDA。我第一次用的时候就被这个名字坑了,以为是I2C接口,接了半天没反应。后来查资料才知道,这个模块支持SPI、I2C、UART三种模式,但默认出厂是SPI模式,板子上印的SDA只是沿用了I2C的丝印习惯。所以你接线的时候,把它当CS用就对了。

配套的卡建议买M1卡(Mifare Classic 1K),这是最通用的,每个扇区有独立的密钥,可以做简单的权限管理。另外备几张UID卡,用来做复制测试。钥匙扣卡和异形卡也可以买几个,做成品的时候好看。

2.2 和ESP32的接线方案

ESP32的SPI引脚不是固定的,大部分GPIO都可以通过矩阵映射成SPI功能,但为了稳定,我习惯用默认的VSPI引脚:

MFRC522引脚ESP32引脚说明
SDA/CSGPIO5片选,低电平有效
SCKGPIO18时钟
MOSIGPIO23主设备输出
MISOGPIO19主设备输入
IRQ不接用轮询方式即可
GNDGND共地
RSTGPIO22复位
3.3V3.3V供电

接线的时候有两条铁律:第一,供电一定是3.3V,不要接5V;第二,GND必须共地,不共地的话SPI通信会时好时坏,这个坑我踩过,查了一晚上才发现是地线没接牢。另外线不要太长,超过20厘米就容易受干扰,读卡距离会明显缩短。

2.3 读卡距离的影响因素

官方标称读卡距离是0到60毫米,但实际用下来,普通M1卡大概在2到3厘米比较稳定。影响距离的因素有几个:天线线圈的大小、卡的朝向、周围有没有金属或强电磁干扰。如果你把模块贴在金属表面上,读卡距离会直接掉到几毫米,因为金属会吸收射频能量。解决办法是在模块和金属之间垫一层绝缘材料,或者干脆换个位置。

提示:调试阶段先把模块悬空放置,不要固定在任何金属或带铜箔的表面上,等程序跑通了再考虑结构安装。

3. SPI通信原理:搞懂它,排查问题快十倍

3.1 SPI到底是怎么工作的

SPI全称是Serial Peripheral Interface,中文叫串行外设接口。你可以把它想象成一条主从结构的流水线:ESP32是主设备,MFRC522是从设备,主设备负责发时钟信号,从设备跟着时钟节拍收发数据。这条流水线上有四根线:SCK是节拍器,MOSI是主设备往从设备送数据,MISO是从设备往主设备送数据,CS是选中信号,告诉从设备“现在轮到你了”。

SPI是全双工的,也就是说发送和接收可以同时进行。每来一个时钟脉冲,主设备移出一位到MOSI,同时从MISO移入一位。所以你在写代码的时候,经常会看到“发送一个字节,同时收到一个字节”这种操作,这不是bug,是SPI的固有特性。

MFRC522的SPI模式支持最高10MHz的时钟,但实际用的时候,我建议先降到1MHz左右调试,稳定之后再往上提。ESP32的SPI时钟分频很灵活,MicroPython里可以直接设波特率,Arduino里通过SPISettings配置。

3.2 片选信号的硬件与软件之分

片选(CS)是SPI里最容易出问题的地方。一个SPI总线上可以挂多个从设备,靠CS来区分。CS有两种控制方式:硬件片选和软件片选。

硬件片选是ESP32的SPI外设自动控制的,你配置好之后,发送数据时硬件会自动拉低对应的CS引脚。软件片选就是你自己用GPIO控制,发送前拉低,发送后拉高。MFRC522模块一般用软件片选就够了,因为总线上通常只有它一个设备。

但这里有个细节:CS拉低和拉高之间,要保证足够的建立时间和保持时间。如果拉得太快,从设备还没反应过来,数据就丢了。我在MicroPython里遇到过这个问题,后来在CS操作之间加了微秒级的延时才稳定。Arduino的库一般已经处理好了,不用太操心。

3.3 寄存器操作的基本逻辑

MFRC522内部有一堆寄存器,读写卡的过程本质上就是通过SPI读写这些寄存器。比如你要寻卡,就是往FIFO寄存器写命令,然后读状态寄存器看结果。MFRC522的寄存器地址是6位的,加上1位读写标志和1位地址对齐,凑成一个字节。

以读一个寄存器为例,流程是这样的:先拉低CS,发送地址字节(最高位置1表示读),然后发送一个空字节,同时从MISO读回寄存器的值,最后拉高CS。写寄存器则是最高位清0,后面跟着要写的数据。这个时序在数据手册里有详细说明,但实际写代码的时候,库函数已经封装好了,你只需要调用PCD_ReadRegister和PCD_WriteRegister就行。

不过理解这个底层逻辑有个好处:当库函数不工作的时候,你可以用逻辑分析仪抓SPI波形,看地址和数据对不对。我有一次读不到卡,抓波形发现地址字节发错了,原因是库版本不匹配,换了个版本就好了。如果不懂底层,这种问题根本无从下手。

4. 开发环境搭建:MicroPython还是Arduino

4.1 两种路线的取舍

ESP32玩RFID,开发环境主要有两条路:MicroPython和Arduino IDE。MicroPython的好处是语法简单,交互式调试方便,适合快速验证想法;Arduino的好处是库多、性能好、社区大,适合做成品。

我个人的习惯是:前期验证用MicroPython,后期成品用Arduino。因为MicroPython的REPL太方便了,接上串口就能一行行试,读卡成功马上能看到UID。但MicroPython的SPI速度相对慢一些,而且断电后程序不会自动运行,需要额外处理。Arduino编译上传后直接跑,稳定性更好。

如果你是完全零基础,我建议先从MicroPython入手,因为门槛低,不容易被编译错误劝退。等把读卡逻辑跑通了,再考虑要不要转Arduino。

4.2 MicroPython固件烧录

MicroPython需要先给ESP32烧录固件。去官网下载对应ESP32型号的固件文件,然后用esptool刷进去。命令大概是这样:

esptool.py --chip esp32 --port /dev/ttyUSB0 erase_flash esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 460800 write_flash -z 0x1000 esp32-20230426-v1.20.0.bin

烧完之后,用串口工具连上去,能看到>>>提示符就说明成功了。然后你需要把MFRC522的驱动库传到板子上。MicroPython的库一般是一个mfrc522.py文件,用ampy或者Thonny直接拖进去就行。

注意:MicroPython固件版本和驱动库版本要匹配,不然会出现ImportError或者寄存器读写异常。我建议用比较新的稳定版固件,驱动库去GitHub找star多的那个。

4.3 Arduino IDE配置要点

Arduino这边,需要在首选项里添加ESP32的开发板管理网址,然后在开发板管理器里安装esp32包。这个过程在国内可能比较慢,因为要下载几百兆的编译工具链。如果网络不好,可以找离线包,或者用PlatformIO,它的依赖管理更顺畅。

装好之后,选对开发板型号,比如ESP32 Dev Module。然后安装MFRC522库,在库管理器里搜MFRC522,选那个by GithubCommunity的版本。这个库封装得比较好,基本功能都有。

编译速度慢是Arduino IDE的老毛病,尤其是第一次编译。有个技巧是把杀毒软件的实时扫描关掉,或者把项目放在SSD上,能快不少。另外,如果你只用SPI和基本GPIO,可以在菜单里把不必要的功能关掉,减少编译量。

5. 代码实战:从读UID到写数据

5.1 MicroPython读卡示例

先来看MicroPython的最小可用代码。这段代码的作用是初始化SPI和MFRC522,然后循环寻卡,读到卡就打印UID。

from machine import Pin, SPI from mfrc522 import MFRC522 import time spi = SPI(1, baudrate=1000000, polarity=0, phase=0, sck=Pin(18), mosi=Pin(23), miso=Pin(19)) cs = Pin(5, Pin.OUT) rst = Pin(22, Pin.OUT) reader = MFRC522(spi, cs, rst) while True: (stat, tag_type) = reader.request(reader.REQIDL) if stat == reader.OK: (stat, uid) = reader.SelectTagSN() if stat == reader.OK: print("Card UID:", [hex(i) for i in uid]) time.sleep(0.5)

这段代码里,REQIDL表示寻感应区内所有卡,SelectTagSN是防冲突后选一张卡并读序列号。UID就是卡的唯一标识,每张卡不一样。读出来之后,你就可以拿这个UID去比对数据库,做权限判断。

有个细节:SPI的极性和相位要设对。MFRC522要求CPOL=0,CPHA=0,也就是空闲时时钟低电平,第一个边沿采样。如果设错了,读出来的数据全是乱的。我在MicroPython里试过设成polarity=1,结果一个字节都读不对,改回来立马正常。

5.2 Arduino读卡与写块

Arduino这边,用MFRC522库读UID更简单:

#include <SPI.h> #include <MFRC522.h> #define SS_PIN 5 #define RST_PIN 22 MFRC522 rfid(SS_PIN, RST_PIN); void setup() { Serial.begin(115200); SPI.begin(); rfid.PCD_Init(); Serial.println("Ready to read..."); } void loop() { if (!rfid.PICC_IsNewCardPresent()) return; if (!rfid.PICC_ReadCardSerial()) return; Serial.print("UID: "); for (byte 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(); }

如果要写数据到卡里,比如往第1扇区的第0块写一个字符串,需要先验证密钥。M1卡默认密钥是FF FF FF FF FF FF。写块的代码大概是这样:

MFRC522::MIFARE_Key key; for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF; byte block = 4; byte data[16] = "Hello RFID!"; if (rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(rfid.uid)) == MFRC522::STATUS_OK) { rfid.MIFARE_Write(block, data, 16); }

写块的时候要注意:每个扇区的第3块是控制块,不能随便写,写错了卡就锁死了。要写数据就写第0、1、2块。另外,写之前一定要验证密钥,验证失败就写不进去。

5.3 断电自动运行的实现

MicroPython默认上电后停在REPL,不会自动跑你的程序。要让程序断电后自动运行,需要把代码保存为main.py,放在文件系统根目录。这样上电后MicroPython会自动执行main.py。

但有个问题:如果main.py里有死循环,REPL就进不去了,调试会很不方便。我的做法是在main.py里加一个按键检测,按住某个键就跳过主程序,直接进REPL。这样既能自动运行,又能随时调试。

Arduino这边不存在这个问题,上传后直接跑,复位就重启。所以如果你要做成品,Arduino的体验更省心。

6. 常见问题排查:读不到卡怎么办

6.1 排查流程速查表

现象可能原因排查方法
完全没反应供电不对万用表量3.3V引脚电压
读不到卡接线松动重新插拔杜邦线,检查GND
读卡距离短天线受干扰移开金属物体,调整卡朝向
数据乱码SPI模式错检查CPOL/CPHA设置
偶尔读到时钟太快降低SPI波特率到500kHz
写卡失败密钥错误确认密钥是否为默认FF
程序不跑固件问题检查main.py是否存在

6.2 几个我踩过的坑

第一个坑是CS引脚接错。我一开始把SDA接到了GPIO21,那是I2C的默认SDA,结果SPI死活不通。后来换成GPIO5就好了。所以接线前一定要确认引脚功能,不要看到SDA就往上接。

第二个坑是电源噪声。我用USB供电的时候读卡正常,换成电池供电就读不到了。后来在3.3V和GND之间加了一个100uF的电解电容,问题解决。原因是电池供电的纹波比较大,影响了射频电路。

第三个坑是卡的类型不对。我买过一批便宜的卡,读UID正常,但写数据总是失败。后来查资料才知道那是只读的UID卡,不能写块。所以买卡的时候要看清是M1卡还是UID卡,用途不一样。

第四个坑是SPI总线冲突。我在同一个SPI总线上还接了一个TFT屏幕,结果两个设备互相干扰。解决办法是给每个设备独立的CS引脚,并且在操作前先拉高其他设备的CS。这个在Arduino里要手动管理,MicroPython里也一样。

提示:调试RFID的时候,先用一张确认能用的卡测试。如果这张卡都读不到,那肯定是硬件或代码问题,不要怀疑卡。

6.3 用逻辑分析仪抓SPI波形

如果以上方法都不行,那就上逻辑分析仪。几十块钱的USB逻辑分析仪就够用,接上SCK、MOSI、MISO、CS四根线,抓一段波形。正常的SPI通信应该能看到CS拉低,然后SCK有8个脉冲,MOSI上有地址字节,MISO上有返回数据。

重点看两个地方:一是CS有没有在通信期间保持低电平,如果中间跳高了,说明片选控制有问题;二是地址字节对不对,比如读版本寄存器应该是0x37,如果发出来不是这个值,说明库或者接线有问题。抓波形这个技能一旦学会,排查SPI设备的问题会快很多。

7. 进阶玩法:从读卡到真正有用的项目

7.1 考勤记录系统

最基本的应用就是考勤。ESP32读到UID后,通过Wi-Fi把UID和时间戳发到服务器,服务器比对数据库,记录签到时间。这个方案的关键是时间同步,ESP32可以用NTP协议从网络获取时间,保证记录准确。

如果要离线运行,可以加一个SD卡模块,把记录写到CSV文件里,联网后再上传。SD卡也是SPI接口,可以和MFRC522共用总线,但要注意CS分开控制。

7.2 门禁控制

门禁比考勤多了一个执行机构,通常是电磁锁或舵机。读到合法UID后,ESP32控制继电器吸合,打开电锁,延时几秒后自动关闭。这里要注意继电器的续流二极管,不然断电瞬间的反向电动势可能烧坏ESP32的IO口。

安全方面,不要只靠UID判断,因为UID是可以复制的。更安全的做法是用M1卡的加密扇区,把密钥分散存储,或者用CPU卡做动态认证。当然,对于普通场景,UID加白名单已经够用了。

7.3 与边缘AI结合

最近有个热词叫“ESP32边缘AI”,其实RFID也能和它结合。比如你可以用ESP32-S3跑一个轻量级神经网络,把刷卡行为序列作为输入,判断是不是异常刷卡。这个玩法比较前沿,需要一定的机器学习基础,但思路是通的:RFID提供身份数据,AI做行为分析。

7.4 无线配网与远程管理

ESP32的Wi-Fi能力可以让RFID设备联网。第一次使用时,通过手机App给ESP32配网,之后它就能自动连接。配网方案可以用SmartConfig或者蓝牙配网,MicroPython和Arduino都有现成库。联网后,你可以远程查看刷卡记录、下发白名单、升级固件,整个系统就活了。

8. 一些实操心得与建议

做RFID项目这几年,我最大的体会是:硬件项目80%的问题出在连接和供电上,代码问题反而好查。所以每次遇到读不到卡,先别急着改代码,拿万用表量一下电压,检查一下接线,往往能省下大量时间。

另外,不要一上来就追求远距离和高速。先把1厘米距离、1MHz时钟跑通,再慢慢优化。我见过太多人一开始就想做10厘米读卡,结果调了几天都没成功,最后发现是天线匹配的问题。循序渐进,每一步都验证,才是最快的路。

最后说个细节:MFRC522模块用久了会发热,尤其是连续读卡的时候。这是正常现象,但如果烫手就不正常了,可能是供电电压偏高或者短路。摸一下模块温度,也是判断硬件状态的一个小技巧。

这个项目后续还可以扩展很多方向,比如加个OLED屏幕显示刷卡结果,加个蜂鸣器做声音提示,或者用ESP32的蓝牙把UID发给手机。核心的读卡逻辑不变,外围想怎么加就怎么加。等你把基础跑通了,这些扩展都是顺手的事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询