TTGO T-Display ESP32外接RC522 SPI模块可识别固件但无法读卡问题
故障核心诱因
- RC522硬复位时序缺失:这是最核心的故障原因。RC522的版本号寄存器属于数字逻辑单元,只要SPI基础通信正常即可读取,但射频收发的模拟前端必须通过RST引脚提供完整的硬复位时序(拉低保持10ms以上再拉高)才能完成校准、启动射频场。直接将RST引脚常置高电平时,仅模块数字部分进入工作状态,射频前端未启动,无法检测卡片。MFRC522库内置的软复位无法完全替代硬复位,市售廉价RC522模块普遍简化了板载复位电路,必须手动控制RST引脚才能完成完整复位。
- SPI配置被TFT初始化覆盖:代码中先初始化TFT屏幕时,会修改全局SPI总线的通信模式、位序、时钟参数,后续初始化RC522时如果没有显式重置SPI配置,会沿用TFT留下的错误参数。单字节的版本号读取容错率高可以正常返回,读卡流程需要连续多字节寄存器交互、FIFO读写,参数不匹配时会直接通信失败。
- SPI时钟速率过高:RC522标称最高支持10MHz SPI时钟,但飞线接线、GPIO重映射场景下信号完整性较差,高速率下连续通信容易出现数据校验错误,导致读卡失败。
- 总线分配判断错误:TTGO T-Display板载TFT默认占用VSPI总线,默认引脚为CLK18/MOSI19,你当前将RC522接在重映射的VSPI引脚(25/26/27)上,并未使用独立的HSPI总线,两个外设实际共用同一SPI主机,没有总线仲裁的情况下会出现配置抢占。
修复方案
方案一:不改动现有接线,软件调整(快速验证)
按以下逻辑修改代码:
- 增加RC522硬复位时序
- 调整初始化顺序,TFT初始化完成后再重映射SPI引脚、初始化RC522,完全覆盖TFT留下的SPI配置
- 显式将RC522的SPI时钟降低到2MHz,提升通信稳定性
- 初始化完成后将TFT的CS引脚(GPIO5)常置高,避免意外选中TFT抢占总线
修正后的可直接运行代码:
#include <SPI.h> #include <MFRC522.h> #include <TFT_eSPI.h> #define RST_PIN 17 #define SS_PIN 33 #define TFT_CS 5 // TTGO T-Display板载TFT固定CS引脚 MFRC522 mfrc522(SS_PIN, RST_PIN); TFT_eSPI tft = TFT_eSPI(); void setup() { Serial.begin(115200); while (!Serial); // 执行RC522硬复位 pinMode(RST_PIN, OUTPUT); digitalWrite(RST_PIN, LOW); delay(15); digitalWrite(RST_PIN, HIGH); delay(5); // 先初始化TFT,完成初始绘制 tft.init(); tft.fillScreen(TFT_WHITE); tft.setCursor(0,0); tft.setTextColor(TFT_BLACK); tft.println("RC522 Test"); // TFT初始化完成后,重映射SPI引脚到RC522接线 SPI.begin(25, 27, 26, SS_PIN); // 参数顺序:CLK, MISO, MOSI, SS // 显式指定SPI总线和2MHz通信速率,重置SPI配置 mfrc522.PCD_Init(SPI, 2000000); delay(10); mfrc522.PCD_DumpVersionToSerial(); // 常拉高TFT_CS,避免TFT抢占总线 pinMode(TFT_CS, OUTPUT); digitalWrite(TFT_CS, HIGH); Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks...")); } void loop() { // 选中RC522,确保TFT未被选中 digitalWrite(TFT_CS, HIGH); digitalWrite(SS_PIN, LOW); if (!mfrc522.PICC_IsNewCardPresent()) { digitalWrite(SS_PIN, HIGH); delay(10); return; } if (!mfrc522.PICC_ReadCardSerial()) { digitalWrite(SS_PIN, HIGH); delay(10); return; } mfrc522.PICC_DumpToSerial(&(mfrc522.uid)); // 释放RC522片选 digitalWrite(SS_PIN, HIGH); delay(10); }
注意:该方案下如果需要后续操作TFT显示读卡内容,必须在调用TFT绘图函数前重新将SPI引脚映射回TFT默认引脚(18, -1, 19, 5),绘图完成后再切回RC522的引脚配置,否则会出现外设无响应的问题。
方案二:改接独立HSPI总线(长期稳定方案,推荐)
如果需要同时稳定使用TFT和RC522,将RC522改接到ESP32独立的HSPI总线上,和TFT的VSPI完全物理隔离,不需要切换引脚、做总线仲裁,稳定性最高:
- 接线调整为:
- RC522 CLK -> GPIO14(HSPI_CLK)
- RC522 MISO -> GPIO12(HSPI_MISO)
- RC522 MOSI -> GPIO13(HSPI_MOSI)
- RC522 CS -> GPIO33(保持原有接线)
- RC522 RST -> GPIO17(保持原有接线)
- 代码仅需修改SPI初始化部分,定义独立的HSPI对象给RC522使用,核心初始化代码替换为:
SPIClass hspi(HSPI); // 定义独立HSPI总线对象 void setup() { // 其他初始化代码不变,TFT正常初始化即可 // ... // 初始化独立HSPI总线给RC522 hspi.begin(14, 12, 13, SS_PIN); mfrc522.PCD_Init(hspi, 2000000); // ... }
额外排查点
- 确保RC522与开发板共地,供电引脚直接接开发板3.3V输出,不要通过细杜邦线长距离供电,RC522工作峰值电流可达100mA,电压跌落会导致射频场功率不足无法读卡
- RC522模块不要贴在TFT屏幕背面安装,屏幕的金属屏蔽层会吸收射频信号,导致读卡距离极短甚至无响应
内容的提问来源于stack exchange,提问作者Pat K.
相关产品推荐
相关产品推荐

