ESP32/ESP8266双SPI配置问题:RFID与SD卡无法同时工作
问题描述
我正在实现读取RFID标签并将数据保存到SD卡的功能,SD卡连接到HSPI总线,RFID连接到VSPI总线。单独运行RFID代码时功能正常,但同时运行两者时SD卡无法工作;修改为SD.begin(cs_pin, HSPISD)后SD卡恢复工作,但RFID又无法正常运行。需要在ESP32和ESP8266上解决该问题。
ESP32引脚配置
RFID_MISO = G19 RFID_MOSI = G23 RFID_SCK = G18 RFID_CS = G5 SD_MISO = G12 SD_MOSI = G13 SD_SCK = G14 SD_CS = G15
测试代码
#include <SPI.h> #include <SD.h> #include <MFRC522.h> File myFile; const int CS = 15; constexpr uint8_t RST_PIN = 22; constexpr uint8_t SS_PIN = 5; String tag; SPIClass VSPIID(VSPI); SPIClass HSPISD(HSPI); MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class MFRC522::MIFARE_Key key; void WriteFile(const char * path, const char * message){ // open the file. note that only one file can be open at a time, // so you have to close this one before opening another. myFile = SD.open(path, FILE_WRITE); // if the file opened okay, write to it: if (myFile) { Serial.printf("Writing to %s ", path); myFile.println(message); myFile.close(); // close the file: Serial.println("completed."); } // if the file didn't open, print an error: else { Serial.println("error opening file "); Serial.println(path); } } void ReadFile(const char * path){ // open the file for reading: myFile = SD.open(path); if (myFile) { Serial.printf("Reading file from %s\n", path); // read from the file until there's nothing else in it: while (myFile.available()) { Serial.write(myFile.read()); } myFile.close(); // close the file: } else { // if the file didn't open, print an error: Serial.println("error opening test.txt"); } digitalWrite(CS, HIGH); // DESELECT (high) SD Card SPI SD.end(); } void setup() { Serial.begin(115200); pinMode(SS_PIN, OUTPUT); pinMode(CS, OUTPUT); VSPIID.begin(); HSPISD.begin(); // pinMode(vspi->pinSS(), OUTPUT); //VSPI SS // pinMode(hspi->pinSS(), OUTPUT); //HSPI SS if (!SD.begin(CS, HSPISD)) { Serial.println("initialization failed!"); } Serial.println("initialization done."); WriteFile("/test.txt", "ElectronicWings.com"); ReadFile("/test.txt"); rfid.PCD_Init(); Serial.println(digitalRead(SS_PIN)); Serial.println(digitalRead(CS)); digitalWrite(CS, HIGH); digitalWrite(SS_PIN, LOW); } void loop() { if (rfid.PICC_IsNewCardPresent()){ if (rfid.PICC_ReadCardSerial()) { for (byte i = 0; i < 4; i++) { tag += rfid.uid.uidByte[i]; } rfid.PICC_HaltA(); rfid.PCD_StopCrypto1(); Serial.println(tag); tag = ""; // if (digitalRead(D3) == LOW){ // while (true) { // delay(100); // if (digitalRead(D3) == HIGH) // break; // } // } } } }
解决方案
针对ESP32的修复
问题核心是MFRC522库默认使用系统默认SPI总线,你手动创建了VSPI实例但未传递给RFID对象,导致总线冲突;同时手动控制片选引脚的逻辑干扰了库的正常操作。
修改要点:
- 给RFID绑定自定义VSPI总线:替换原RFID实例化代码,将自定义VSPI实例传入
MFRC522 rfid(SS_PIN, RST_PIN, &VSPIID); - 显式初始化SPI总线引脚:避免总线引脚复用冲突,初始化时指定对应引脚
VSPIID.begin(18, 19, 23, SS_PIN); // VSPI: SCK=G18, MISO=G19, MOSI=G23, CS=G5 HSPISD.begin(14, 12, 13, CS); // HSPI: SCK=G14, MISO=G12, MOSI=G13, CS=G15 - 移除手动拉低RFID片选的代码:片选逻辑由MFRC522库自动处理,手动拉低会导致设备一直被选中,干扰总线
- 修复SD卡操作逻辑:移除
ReadFile()中的SD.end(),仅在操作后拉高片选即可,否则后续使用SD卡需要重新初始化
修改后的核心代码片段:
// 替换RFID实例化 MFRC522 rfid(SS_PIN, RST_PIN, &VSPIID); // 修改ReadFile函数 void ReadFile(const char * path){ myFile = SD.open(path); if (myFile) { Serial.printf("Reading file from %s\n", path); while (myFile.available()) { Serial.write(myFile.read()); } myFile.close(); } else { Serial.println("error opening test.txt"); } digitalWrite(CS, HIGH); // 仅拉高片选,不调用SD.end() } // 修改setup函数 void setup() { Serial.begin(115200); pinMode(SS_PIN, OUTPUT); pinMode(CS, OUTPUT); // 显式初始化两个SPI总线 VSPIID.begin(18, 19, 23, SS_PIN); HSPISD.begin(14, 12, 13, CS); if (!SD.begin(CS, HSPISD)) { Serial.println("SD卡初始化失败!"); } Serial.println("SD卡初始化完成."); WriteFile("/test.txt", "ElectronicWings.com"); ReadFile("/test.txt"); // 初始化RFID rfid.PCD_Init(); // 确保两个设备片选都处于未选中状态 digitalWrite(CS, HIGH); digitalWrite(SS_PIN, HIGH); }
针对ESP8266的修复
ESP8266只有一组硬件SPI总线,无法像ESP32那样拆分VSPI/HSPI,因此需要用软件模拟SPI给其中一个设备使用,避免总线冲突(建议SD卡用硬件SPI以保证读写速度)。
修改要点:
- 引入
SoftwareSPI库,为RFID创建软件SPI实例 - 将RFID绑定到软件SPI总线,SD卡保留硬件SPI
示例代码片段:
#include <SPI.h> #include <SD.h> #include <MFRC522.h> #include <SoftwareSPI.h> // SD卡硬件SPI引脚 const int SD_CS = 15; // RFID软件SPI引脚 constexpr uint8_t RFID_RST = 22; constexpr uint8_t RFID_CS = 5; constexpr uint8_t RFID_SCK = 18; constexpr uint8_t RFID_MISO = 19; constexpr uint8_t RFID_MOSI = 23; // 创建软件SPI实例 SoftwareSPI rfidSpi(RFID_SCK, RFID_MOSI, RFID_MISO); // 将RFID绑定到软件SPI MFRC522 rfid(RFID_CS, RFID_RST, &rfidSpi); void setup() { Serial.begin(115200); // 初始化SD卡(硬件SPI) if (!SD.begin(SD_CS)) { Serial.println("SD卡初始化失败!"); } Serial.println("SD卡初始化完成."); // 初始化RFID软件SPI rfidSpi.begin(); rfid.PCD_Init(); }
内容的提问来源于stack exchange,提问作者LoNE WoLvES
相关产品推荐
相关产品推荐

