遇到的问题:

SD卡出初始化总是失败

硬件准备:闪送了一张 闪迪的16G SD卡,和读卡器,用PC格式化为了 FAT32格式和4096 块大小

卡买来就是FAT32,一开始代码没写对,所以就跟着AI提醒做了上述操作,也不知道有没有用。

应该还是代码中初始化代码没写对,AI只给了一句 这样的代码,总是初始化失败。

SD_MMC.begin("/sdcard", false)

板子信息如下,

SD卡槽也看不到具体插的哪个口,后来AI给了一段尝试各种主流型号的口的代码

/*
 * GOOUUU ESP32-S3-CAM v1.3 SD 卡文件列表程序
 * 功能:初始化 SD 卡并打印根目录所有文件名
 * 
 * SD 卡引脚配置(自动尝试多种组合):
 * 组合 A: CLK=39, CMD=38, D0=40 (Freenove 风格)
 * 组合 B: CLK=39, CMD=40, D0=47 (Diymore 风格)
 * 组合 C: CLK=36, CMD=35, D0=37 (DevKitC 风格)
 * 组合 D: CLK=6,  CMD=7,  D0=4  (早期 S3 风格)
 */

#include <SD_MMC.h>

// 定义要尝试的引脚组合
struct SD_Pins {
  const char* name;
  int clk;
  int cmd;
  int d0;
};

SD_Pins pinConfigs[] = {
  {"Freenove风格 (39,38,40)", 39, 38, 40},
  {"Diymore风格 (39,40,47)",  39, 40, 47},
  {"DevKitC风格 (36,35,37)",  36, 35, 37},
  {"早期S3风格 (6,7,4)",      6,  7,  4},
  {"XIAO风格 (7,9,8)",        7,  9,  8}
};

void setup() {
  Serial.begin(115200);
  delay(2000);
  
  Serial.println("\n========================================");
  Serial.println("GOOUUU ESP32-S3-CAM v1.3 SD 卡测试");
  Serial.println("========================================");
  
  // 打印芯片信息
  Serial.print("芯片型号: ESP32-S3 (");
  Serial.print(ESP.getChipRevision());
  Serial.println(")");
  Serial.printf("Flash: %d MB\n", ESP.getFlashChipSize() / (1024 * 1024));
  Serial.printf("PSRAM: %d MB\n", ESP.getPsramSize() / (1024 * 1024));
  Serial.println("----------------------------------------\n");
  
  // 尝试每种引脚配置
  bool sdOk = false;
  
  for (int i = 0; i < sizeof(pinConfigs) / sizeof(pinConfigs[0]); i++) {
    Serial.printf("[尝试 %d/%d] %s\n", i + 1, 
                  sizeof(pinConfigs) / sizeof(pinConfigs[0]), 
                  pinConfigs[i].name);
    Serial.printf("  CLK=%d, CMD=%d, D0=%d\n", 
                  pinConfigs[i].clk, pinConfigs[i].cmd, pinConfigs[i].d0);
    
    if (tryInitSD(pinConfigs[i].clk, pinConfigs[i].cmd, pinConfigs[i].d0)) {
      Serial.println("  ✓ SD 卡初始化成功!");
      sdOk = true;
      break;
    } else {
      Serial.println("  ✗ 失败");
    }
    Serial.println();
  }
  
  if (!sdOk) {
    Serial.println("\n========================================");
    Serial.println("所有引脚组合都失败!");
    Serial.println("请检查:");
    Serial.println("1. SD 卡是否正确插入");
    Serial.println("2. SD 卡是否格式化为 FAT32");
    Serial.println("3. 开发板是否有物理损坏");
    Serial.println("========================================");
    return;
  }
  
  // 打印 SD 卡信息
  printSDInfo();
  
  // 列出根目录文件
  Serial.println("\n========================================");
  Serial.println("SD 卡根目录文件列表:");
  Serial.println("----------------------------------------");
  listRootDirectory();
  Serial.println("========================================");
}

void loop() {
  // 空循环
}

// ==================== 辅助函数 ====================

bool tryInitSD(int clk, int cmd, int d0) {
  // 先卸载之前的实例
  SD_MMC.end();
  delay(100);
  
  // 设置引脚(仅 ESP32-S3 支持)
  #ifdef CONFIG_IDF_TARGET_ESP32S3
    if (!SD_MMC.setPins(clk, cmd, d0)) {
      Serial.println("    setPins() 返回 false");
      return false;
    }
  #endif
  
  // 尝试 1-bit 模式初始化
  if (SD_MMC.begin("/sdcard", true)) {
    return true;
  }
  
  return false;
}

void printSDInfo() {
  uint8_t cardType = SD_MMC.cardType();
  
  Serial.println("\n----------------------------------------");
  Serial.print("SD 卡类型: ");
  switch (cardType) {
    case CARD_NONE: Serial.println("未检测到"); break;
    case CARD_MMC:  Serial.println("MMC"); break;
    case CARD_SD:   Serial.println("SDSC (标准容量)"); break;
    case CARD_SDHC: Serial.println("SDHC (高容量)"); break;
    default:        Serial.println("未知"); break;
  }
  
  if (cardType != CARD_NONE) {
    uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
    uint64_t totalBytes = SD_MMC.totalBytes() / (1024 * 1024);
    uint64_t usedBytes = SD_MMC.usedBytes() / (1024 * 1024);
    
    Serial.printf("SD 卡容量: %llu MB\n", cardSize);
    Serial.printf("文件系统总空间: %llu MB\n", totalBytes);
    Serial.printf("已用空间: %llu MB\n", usedBytes);
    Serial.printf("可用空间: %llu MB\n", totalBytes - usedBytes);
  }
  Serial.println("----------------------------------------");
}

void listRootDirectory() {
  File root = SD_MMC.open("/");
  
  if (!root) {
    Serial.println("错误:无法打开根目录");
    return;
  }
  
  if (!root.isDirectory()) {
    Serial.println("错误:根目录不是文件夹");
    return;
  }
  
  int fileCount = 0;
  int dirCount = 0;
  
  File file = root.openNextFile();
  
  if (!file) {
    Serial.println("(根目录为空)");
  }
  
  while (file) {
    if (file.isDirectory()) {
      Serial.printf("[DIR]  %s/\n", file.name());
      dirCount++;
    } else {
      Serial.printf("[FILE] %-30s %10d bytes\n", file.name(), file.size());
      fileCount++;
    }
    file = root.openNextFile();
  }
  
  Serial.println("----------------------------------------");
  Serial.printf("总计: %d 个文件, %d 个文件夹\n", fileCount, dirCount);
}

代码说明

自动探测引脚组合

代码会自动尝试 5 种常见的 ESP32-S3-CAM SD 卡引脚配置:

表格

组合 CLK CMD D0 适用开发板
Freenove 39 38 40 Freenove ESP32-S3-CAM
Diymore 39 40 47 Diymore/某些 GOOUUU
DevKitC 36 35 37 ESP32-S3-DevKitC
早期 S3 6 7 4 早期 ESP32-S3 设计
XIAO 7 9 8 Seeed XIAO ESP32S3

运气不错,第一个组合就测出来了

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x29 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3818,len:0x508
load:0x403c9700,len:0x4
load:0x403c9704,len:0xad0
load:0x403cc700,len:0x29e4
entry 0x403c9880

========================================
GOOUUU ESP32-S3-CAM v1.3 SD 卡测试
========================================
芯片型号: ESP32-S3 (2)
Flash: 16 MB
PSRAM: 8 MB
----------------------------------------

[尝试 1/5] Freenove风格 (39,38,40)
  CLK=39, CMD=38, D0=40
  ✓ SD 卡初始化成功!

----------------------------------------
SD 卡类型: SDHC (高容量)
SD 卡容量: 15200 MB
文件系统总空间: 15167 MB
已用空间: 2 MB
可用空间: 15165 MB
----------------------------------------

========================================
SD 卡根目录文件列表:
----------------------------------------
[DIR]  System Volume Information/
[FILE] audio1.wav                         265004 bytes
[FILE] audio2.wav                         311084 bytes
[FILE] audio3.wav                         291884 bytes
[FILE] audio4.wav                         483884 bytes
[FILE] audio5.wav                         487724 bytes
[FILE] hello.wav                          288044 bytes
----------------------------------------
总计: 6 个文件, 1 个文件夹
========================================

从输出来看,买的这个板子是第一种风格, Freenove风格 (39,38,40),

对应的端口:  CLK=39, CMD=38, D0=40

知道了端口就可以简化下代码了,让AI简化了下代码如下:

/*
 * GOOUUU ESP32-S3-CAM v1.3 SD 卡文件浏览器
 * 引脚: CLK=39, CMD=38, D0=40
 */

#include <SD_MMC.h>

#define SD_CLK  39
#define SD_CMD  38
#define SD_D0   40

void setup() {
  Serial.begin(115200);
  delay(1000);
  
  Serial.println("\n========================================");
  Serial.println("ESP32-S3-CAM v1.3 SD 卡文件列表");
  Serial.println("========================================");
  
  // 初始化 SD 卡
  SD_MMC.setPins(SD_CLK, SD_CMD, SD_D0);
  
  if (!SD_MMC.begin("/sdcard", true)) {
    Serial.println("SD 卡初始化失败");
    return;
  }
  
  // 打印卡信息
  uint8_t type = SD_MMC.cardType();
  Serial.print("卡类型: ");
  if (type == CARD_SD) Serial.println("SD");
  else if (type == CARD_SDHC) Serial.println("SDHC");
  else if (type == CARD_MMC) Serial.println("MMC");
  else Serial.println("未知");
  
  Serial.printf("容量: %llu MB\n", SD_MMC.cardSize() / 1048576);
  Serial.printf("已用: %llu MB\n\n", SD_MMC.usedBytes() / 1048576);
  
  // 列出根目录
  listDir("/");
}

void loop() {}

void listDir(const char* path) {
  File root = SD_MMC.open(path);
  if (!root || !root.isDirectory()) return;
  
  File file = root.openNextFile();
  while (file) {
    if (file.isDirectory()) {
      Serial.printf("[DIR]  %s/\n", file.name());
    } else {
      Serial.printf("[FILE] %-25s %8d bytes\n", file.name(), file.size());
    }
    file = root.openNextFile();
  }
}

输出结果如下:

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x9 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3818,len:0x508
load:0x403c9700,len:0x4
load:0x403c9704,len:0xad0
load:0x403cc700,len:0x29e4
entry 0x403c9880

========================================
ESP32-S3-CAM v1.3 SD 卡文件列表
========================================
卡类型: SDHC
容量: 15200 MB
已用: 2 MB

[DIR]  System Volume Information/
[FILE] audio1.wav                  265004 bytes
[FILE] audio2.wav                  311084 bytes
[FILE] audio3.wav                  291884 bytes
[FILE] audio4.wav                  483884 bytes
[FILE] audio5.wav                  487724 bytes
[FILE] hello.wav                   288044 bytes

总结:在板子上加了什么硬件,都要配置端口号,如果没有对应的端口,就要测出来端口,否则徒劳。

下一篇,要通过外接功放和喇叭,播放SD卡里的音频

更多推荐