sd卡模块与其他SPI设备共同使用,存在的问题

2026-09-0713

很久之前我曾经发布过的问题贴。当时也没搞懂,反正最终弄了个方案也算解决了,解决的方式也不太好。
现在有了AI,再去查一些资料也更快了,更全了。现在能正确回答并解决这个问题了。

问题就出在SD卡模块了。
一般买到的SD卡模块是这个样子的。网上找的图。
sd卡模块与其他SPI设备共同使用,存在的问题_image_1.webp
这个SD卡模块有2个芯片:一个LVC125,也就是4路的三态门;一个AMS1117,也就是3.3V的稳压器。
sd卡模块与其他SPI设备共同使用,存在的问题_image_2.webp
SD卡是一个3.3V的设备,一般单片机输出的高电平是5V的信号,不能直接用。所以SD卡模块就用上了上述2个芯片。
问题就出在这个LVC125芯片的使用上了。
它把SD卡的SCK,MISO,MOSI,CS,这4个引脚,都接入到LVC125上了,并且把LVC125的4个使能引脚OE,都直接接GND了,也就是一直处于导通。这里重点问题是MISO引脚,也就是Master Input Slave Output,主机输入从机输出,SD卡模块给arduino发送信号协议的引脚。

在SPI协议里,如果通过拉高片选引脚,让一个SPI设备不生效,应该要让MISO引脚处于高阻态/悬空的。
但是由于这种错误的连接方式,当你试图拉高SD卡模块的片选引脚时,本来是希望让SD卡模块离线,对应的MISO引脚也应该断开,但是LVC125的使能引脚一直接地,这会让MISO引脚一直处于导通的状态。其他SPI设备MISO引脚发出的信号,就会和SD卡模块的MISO引脚有冲突。
从而导致了其他设备的异常情况。

所以更规范的连接方式应该是,把LVC125接入MISO的使能信号,也接入到SD卡的片选引脚CS上,通过SD卡的片选引脚CS,来控制MISO的开闭。

那现在的解决方式一般有2种:难度高的,就是自己改SD卡模块,把LVC125,接入MISO的使能引脚给断开,再用个飞线,接到CS上。

难度低的,就是自己再弄个三态门,把SD卡模块的MISO引脚,接入到输入端;输出端接入到单片机的MISO,把使能引脚接入到SD卡的片选引脚上。

给个示例代码,SD卡模块与RFID模块,共用的例子。RFID扫描到卡后,读取SD卡的一个文件,并通过串口输出。

#include <SPI.h>
#include <MFRC522.h>
#include <SD.h>

#define SD_CS   4
#define RFID_CS 10
#define RFID_RST 9

MFRC522 rfid(RFID_CS, RFID_RST);

void setup() {
  Serial.begin(9600);
  while (!Serial);

  SPI.begin();
  
  // 初始化 SD 卡(只一次)
  pinMode(SD_CS, OUTPUT);
  pinMode(RFID_CS, OUTPUT);
  digitalWrite(RFID_CS, HIGH);
  digitalWrite(SD_CS, HIGH);
  
  if (!SD.begin(SD_CS)) {
    Serial.println("SD 初始化失败!");
  } else {
    Serial.println("SD 初始化成功。");
  }
  
  // 初始化 RFID(只一次)
  rfid.PCD_Init();
  Serial.println("RFID 初始化完成。");
  rfid.PCD_DumpVersionToSerial();
}

void loop() {
  // ----- 读 RFID 卡 -----
  digitalWrite(SD_CS, HIGH);   // 取消选中 SD 卡
  digitalWrite(RFID_CS, LOW);  // 选中 RFID
  
  if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
    Serial.print("卡片 UID: ");
    for (byte i = 0; i < rfid.uid.size; i++) {
      Serial.print(rfid.uid.uidByte[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
    
    // 读取完成后,让卡片进入休眠
    rfid.PICC_HaltA();
    rfid.PCD_StopCrypto1();
    
    // 结束 RFID 事务,释放总线
    digitalWrite(RFID_CS, HIGH);
    
    // ----- 读 SD 卡文件 -----
    digitalWrite(SD_CS, LOW);
    File dataFile = SD.open("datalog.txt");
    if (dataFile) {
      while (dataFile.available()) {
        Serial.write(dataFile.read());
      }
      dataFile.close();
    } else {
      Serial.println("打开文件失败");
    }
    delay(1500);
  }
  delay(200);
}

原帖:Arduino Uno 板 SD 模块 与 RFID 模块不能共用

创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(0)
- 没有更多了 -