Arduino ESP32 读取SD卡接口选择参考

ESP32 读取SD卡接口选择参考


ESP3232读取SD卡可以通过spi和sdmmc两种方式来读取,不过我们在市面上能买到的都基本上是4线的SPI接口的SD卡模块套件。

  • 卡类型有如下,8-9Pin被引出,但是安装到我们的卡套上就只剩下MOSI,MISO,SCK,CS,GND,VCC
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

ESP32一共有3组SPI接口

除了下面2两组,另外一组给片上的SPI flash使用。
在这里插入图片描述

SD接口

在Arduino libraries库当中SD接口大多采用的SD SPI总线传输模式。
SD实际上有更多的传输模式:

  • SPI总线模式:ESP32有1个以上的SPI总线,可以在初始化时自定义.
  • 1位/ 4位SD总线模式:ESP32提供了另一个名为SD_MMC的库来实现SD总线模式API
  • SD UHS-II模式:ESP32不支持.

ESP32 SPI接口,GPIO引脚映射

在这里插入图片描述

1位/ 4位SD总线的GPIO引脚映射不能更改。

  • 简单调用SD_MMC begin()初始4位SD总线模式:
    在这里插入图片描述
SD_MMC.begin();
  • 可以在SD_MMC begin()方法中选择1位SD总线模式:
SD_MMC.begin("/cdcard", true);
  • 可以在创建SPIClass实例时选择SPI总线(HSPI或VSPI)
SPIClass spi = SPIClass(HSPI);

如你所见,1位/ 4位SD总线引脚与HSPI共享引脚,但SD卡引脚的映射是不一样的。所以如果硬件按照SD总线的引脚图连接,就不能直接使用HSPI本地引脚。GPIO脚可以在SPIClass begin()方法中覆盖.

SPIClass spi = SPIClass(HSPI);
spi.begin(14 /* SCK */, 2 /* MISO */, 15 /* MOSI */, 13 /* SS */);

SD库也可以在SD begin()方法中覆盖SS引脚、SPI总线和总线频率.

SD.begin(13 /* SS */, spi, 80000000);

不同模式下的测试的下载速度

在这里插入图片描述
在这里插入图片描述

测试程序

/*
 * Connect the SD card to the following pins:
 *
 * SD Card | ESP32
 *    D2       12
 *    D3       13
 *    CMD      15
 *    VSS      GND
 *    VDD      3.3V
 *    CLK      14
 *    VSS      GND
 *    D0       2  (add 1K pull up after flashing)
 *    D1       4
 */
#include "FS.h"
#include "SD.h"
#include "SD_MMC.h"

#define TEST_FILE_SIZE (4 * 1024 * 1024)

void testWriteFile(fs::FS &fs, const char *path, uint8_t *buf, int len)
{
  unsigned long start_time = millis();
  Serial.printf("Test write %s\n", path);

  File file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  int loop = TEST_FILE_SIZE / len;
  while (loop--)
  {
    if (!file.write(buf, len)) {
      Serial.println("Write failed");
      return;
    }
  }
  file.flush();
  file.close();
  unsigned long time_used = millis() - start_time;
  Serial.printf("Write file used: %d ms, %f KB/s\n", time_used, (float)TEST_FILE_SIZE / time_used);
}

void testReadFile(fs::FS &fs, const char *path, uint8_t *buf, int len)
{
  unsigned long start_time = millis();
  Serial.printf("Test read %s\n", path);

  File file = fs.open(path);
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }
  int loop = TEST_FILE_SIZE / len;
  while (loop--)
  {
    if (!file.read(buf, len)) {
      Serial.println("Read failed");
      return;
    }
  }
  file.close();
  unsigned long time_used = millis() - start_time;
  Serial.printf("Read file used: %d ms, %f KB/s\n", time_used, (float)TEST_FILE_SIZE / time_used);
}

void testIO(fs::FS &fs)
{
  /* malloc will not reset all bytes to zero, so it is a random data */
  uint8_t *buf = (uint8_t*)malloc(64 * 1024);

  testWriteFile(fs, "/test_1k.bin", buf, 1024);
  testWriteFile(fs, "/test_2k.bin", buf, 2 * 1024);
  testWriteFile(fs, "/test_4k.bin", buf, 4 * 1024);
  testWriteFile(fs, "/test_8k.bin", buf, 8 * 1024);
  testWriteFile(fs, "/test_16k.bin", buf, 16 * 1024);
  testWriteFile(fs, "/test_32k.bin", buf, 32 * 1024);
  testWriteFile(fs, "/test_64k.bin", buf, 64 * 1024);

  testReadFile(fs, "/test_1k.bin", buf, 1024);
  testReadFile(fs, "/test_2k.bin", buf, 2 * 1024);
  testReadFile(fs, "/test_4k.bin", buf, 4 * 1024);
  testReadFile(fs, "/test_8k.bin", buf, 8 * 1024);
  testReadFile(fs, "/test_16k.bin", buf, 16 * 1024);
  testReadFile(fs, "/test_32k.bin", buf, 32 * 1024);
  testReadFile(fs, "/test_64k.bin", buf, 64 * 1024);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  /* test SD_MMC 4-bit Mode */
//  if (!SD_MMC.begin()) {
//    Serial.println("Card Mount Failed");
//    return;
//  }
//  testIO(SD_MMC);

  /* test SD_MMC 1-bit Mode */
  if (!SD_MMC.begin("/cdcard", true)) {
    Serial.println("Card Mount Failed");
    return;
  }
  testIO(SD_MMC);

  /* test SD SPI Mode at HSPI */
//  SPIClass spi = SPIClass(HSPI);
//  spi.begin(14 /* SCK */, 2 /* MISO */, 15 /* MOSI */, 13 /* SS */);
//  if (!SD.begin(13 /* SS */, spi, 80000000)) {
//    Serial.println("Card Mount Failed");
//    return;
//  }
//  testIO(SD);

  /* test SD SPI Mode at VSPI */
//  SPIClass spi = SPIClass(VSPI);
//  spi.begin(18 /* SCK */, 19 /* MISO */, 23 /* MOSI */, 5 /* SS */);
//  if (!SD.begin(5 /* SS */, spi, 80000000)) {
//    Serial.println("Card Mount Failed");
//    return;
//  }
//  testIO(SD);
}

void loop() {
}
  • SD_MMC 4位模式基准测试

SanDisk 8 GB MicroSD

20:28:17.248 -> Write file used: 17834 ms, 235.185822 KB/s
20:28:17.248 -> Test write /test_4k.bin
20:28:21.122 -> Write file used: 3873 ms, 1082.959961 KB/s
20:28:21.122 -> Test write /test_8k.bin
20:28:23.147 -> Write file used: 2024 ms, 2072.284668 KB/s
20:28:23.147 -> Test write /test_16k.bin
20:28:27.237 -> Write file used: 4097 ms, 1023.750061 KB/s
20:28:27.237 -> Test write /test_32k.bin
20:28:30.088 -> Write file used: 2842 ms, 1475.828247 KB/s
20:28:30.088 -> Test write /test_64k.bin
20:28:31.882 -> Write file used: 1811 ms, 2316.015381 KB/s
20:28:31.882 -> Test read /test_1k.bin
20:28:35.422 -> Read file used: 3520 ms, 1191.563599 KB/s
20:28:35.422 -> Test read /test_2k.bin
20:28:38.813 -> Read file used: 3389 ms, 1237.622925 KB/s
20:28:38.813 -> Test read /test_4k.bin
20:28:42.273 -> Read file used: 3474 ms, 1207.341431 KB/s
20:28:42.273 -> Test read /test_8k.bin
20:28:45.752 -> Read file used: 3487 ms, 1202.840210 KB/s
20:28:45.752 -> Test read /test_16k.bin
20:28:48.988 -> Read file used: 3213 ms, 1305.416748 KB/s
20:28:48.988 -> Test read /test_32k.bin
20:28:52.077 -> Read file used: 3093 ms, 1356.063354 KB/s
20:28:52.077 -> Test read /test_64k.bin
20:28:55.141 -> Read file used: 3080 ms, 1361.786987 KB/s
  • SD_MMC 1位模式基准测试

SanDisk 8 GB MicroSD

20:31:45.194 -> Test write /test_1k.bin
20:31:59.506 -> Write file used: 14325 ms, 292.796082 KB/s
20:31:59.506 -> Test write /test_2k.bin
20:32:17.686 -> Write file used: 18163 ms, 230.925735 KB/s
20:32:17.686 -> Test write /test_4k.bin
20:32:21.291 -> Write file used: 3611 ms, 1161.535278 KB/s
20:32:21.291 -> Test write /test_8k.bin
20:32:23.939 -> Write file used: 2652 ms, 1581.562622 KB/s
20:32:23.939 -> Test write /test_16k.bin
20:32:28.397 -> Write file used: 4448 ms, 942.964050 KB/s
20:32:28.397 -> Test write /test_32k.bin
20:32:31.835 -> Write file used: 3429 ms, 1223.185791 KB/s
20:32:31.835 -> Test write /test_64k.bin
20:32:33.882 -> Write file used: 2058 ms, 2038.048584 KB/s
20:32:33.882 -> Test read /test_1k.bin
20:32:38.031 -> Read file used: 4146 ms, 1011.650757 KB/s
20:32:38.031 -> Test read /test_2k.bin
20:32:42.062 -> Read file used: 4019 ms, 1043.618774 KB/s
20:32:42.062 -> Test read /test_4k.bin
20:32:46.170 -> Read file used: 4106 ms, 1021.506104 KB/s
20:32:46.170 -> Test read /test_8k.bin
20:32:50.288 -> Read file used: 4121 ms, 1017.787903 KB/s
20:32:50.288 -> Test read /test_16k.bin
20:32:54.112 -> Read file used: 3840 ms, 1092.266724 KB/s
20:32:54.112 -> Test read /test_32k.bin
20:32:57.840 -> Read file used: 3739 ms, 1121.771606 KB/s
20:32:57.840 -> Test read /test_64k.bin
20:33:01.568 -> Read file used: 3711 ms, 1130.235474 KB/s

Old 128 MB MicroSD

20:33:27.366 -> Test write /test_1k.bin
20:33:42.386 -> Write file used: 15020 ms, 279.247925 KB/s
20:33:42.386 -> Test write /test_2k.bin
20:33:57.927 -> Write file used: 15515 ms, 270.338654 KB/s
20:33:57.927 -> Test write /test_4k.bin
20:34:13.108 -> Write file used: 15195 ms, 276.031860 KB/s
20:34:13.108 -> Test write /test_8k.bin
20:34:28.162 -> Write file used: 15048 ms, 278.728333 KB/s
20:34:28.162 -> Test write /test_16k.bin
20:34:43.287 -> Write file used: 15142 ms, 276.998016 KB/s
20:34:43.287 -> Test write /test_32k.bin
20:34:58.278 -> Write file used: 14964 ms, 280.292969 KB/s
20:34:58.278 -> Test write /test_64k.bin
20:35:13.370 -> Write file used: 15101 ms, 277.750092 KB/s
20:35:13.370 -> Test read /test_1k.bin
20:35:17.563 -> Read file used: 4197 ms, 999.357666 KB/s
20:35:17.563 -> Test read /test_2k.bin
20:35:21.746 -> Read file used: 4191 ms, 1000.788330 KB/s
20:35:21.746 -> Test read /test_4k.bin
20:35:25.942 -> Read file used: 4181 ms, 1003.182007 KB/s
20:35:25.942 -> Test read /test_8k.bin
20:35:30.101 -> Read file used: 4176 ms, 1004.383118 KB/s
20:35:30.101 -> Test read /test_16k.bin
20:35:34.279 -> Read file used: 4174 ms, 1004.864380 KB/s
20:35:34.279 -> Test read /test_32k.bin
20:35:38.462 -> Read file used: 4173 ms, 1005.105225 KB/s
20:35:38.462 -> Test read /test_64k.bin
20:35:42.612 -> Read file used: 4173 ms, 1005.105225 KB/s
  • 在HSPI总线基准的SD SPI模式

SanDisk 8 GB MicroSD

08:41:19.703 -> Test write /test_1k.bin
08:41:53.458 -> Write file used: 33743 ms, 124.301453 KB/s
08:41:53.458 -> Test write /test_2k.bin
08:42:10.000 -> Write file used: 16540 ms, 253.585495 KB/s
08:42:10.000 -> Test write /test_4k.bin
08:42:17.269 -> Write file used: 7298 ms, 574.719666 KB/s
08:42:17.308 -> Test write /test_8k.bin
08:42:22.640 -> Write file used: 5345 ms, 784.715454 KB/s
08:42:22.640 -> Test write /test_16k.bin
08:42:32.285 -> Write file used: 9662 ms, 434.103088 KB/s
08:42:32.285 -> Test write /test_32k.bin
08:42:36.659 -> Write file used: 4355 ms, 963.100830 KB/s
08:42:36.659 -> Test write /test_64k.bin
08:42:39.594 -> Write file used: 2949 ms, 1422.280151 KB/s
08:42:39.594 -> Test read /test_1k.bin
08:42:44.774 -> Read file used: 5192 ms, 807.839783 KB/s
08:42:44.774 -> Test read /test_2k.bin
08:42:49.969 -> Read file used: 5189 ms, 808.306824 KB/s
08:42:49.969 -> Test read /test_4k.bin
08:42:55.123 -> Read file used: 5161 ms, 812.692139 KB/s
08:42:55.158 -> Test read /test_8k.bin
08:43:00.300 -> Read file used: 5176 ms, 810.336914 KB/s
08:43:00.334 -> Test read /test_16k.bin
08:43:05.277 -> Read file used: 4948 ms, 847.676636 KB/s
08:43:05.277 -> Test read /test_32k.bin
08:43:10.028 -> Read file used: 4773 ms, 878.756348 KB/s
08:43:10.028 -> Test read /test_64k.bin
08:43:14.760 -> Read file used: 4731 ms, 886.557617 KB/s

Old 128 MB MicroSD

08:43:47.777 -> Test write /test_1k.bin
08:44:04.148 -> Write file used: 16390 ms, 255.906281 KB/s
08:44:04.183 -> Test write /test_2k.bin
08:44:20.648 -> Write file used: 16494 ms, 254.292709 KB/s
08:44:20.648 -> Test write /test_4k.bin
08:44:36.674 -> Write file used: 16001 ms, 262.127625 KB/s
08:44:36.674 -> Test write /test_8k.bin
08:44:52.849 -> Write file used: 16175 ms, 259.307831 KB/s
08:44:52.849 -> Test write /test_16k.bin
08:45:09.225 -> Write file used: 16397 ms, 255.797043 KB/s
08:45:09.225 -> Test write /test_32k.bin
08:45:25.363 -> Write file used: 16143 ms, 259.821838 KB/s
08:45:25.397 -> Test write /test_64k.bin
08:45:41.632 -> Write file used: 16263 ms, 257.904694 KB/s
08:45:41.632 -> Test read /test_1k.bin
08:45:46.488 -> Read file used: 4856 ms, 863.736389 KB/s
08:45:46.488 -> Test read /test_2k.bin
08:45:51.332 -> Read file used: 4840 ms, 866.591736 KB/s
08:45:51.332 -> Test read /test_4k.bin
08:45:56.163 -> Read file used: 4834 ms, 867.667358 KB/s
08:45:56.163 -> Test read /test_8k.bin
08:46:00.998 -> Read file used: 4827 ms, 868.925598 KB/s
08:46:00.998 -> Test read /test_16k.bin
08:46:05.808 -> Read file used: 4825 ms, 869.285828 KB/s
08:46:05.843 -> Test read /test_32k.bin
08:46:10.637 -> Read file used: 4824 ms, 869.466003 KB/s
08:46:10.637 -> Test read /test_64k.bin
08:46:15.478 -> Read file used: 4825 ms, 869.285828 KB/s
  • 在VSPI总线基准的SD SPI模式

SanDisk 8 GB MicroSD

08:54:17.412 -> Test write /test_1k.bin
08:54:48.398 -> Write file used: 30994 ms, 135.326324 KB/s
08:54:48.398 -> Test write /test_2k.bin
08:55:06.079 -> Write file used: 17677 ms, 237.274658 KB/s
08:55:06.079 -> Test write /test_4k.bin
08:55:13.357 -> Write file used: 7274 ms, 576.615906 KB/s
08:55:13.357 -> Test write /test_8k.bin
08:55:18.691 -> Write file used: 5323 ms, 787.958679 KB/s
08:55:18.691 -> Test write /test_16k.bin
08:55:28.336 -> Write file used: 9669 ms, 433.788818 KB/s
08:55:28.336 -> Test write /test_32k.bin
08:55:32.646 -> Write file used: 4309 ms, 973.382202 KB/s
08:55:32.646 -> Test write /test_64k.bin
08:55:35.551 -> Write file used: 2915 ms, 1438.869263 KB/s
08:55:35.584 -> Test read /test_1k.bin
08:55:40.745 -> Read file used: 5183 ms, 809.242554 KB/s
08:55:40.745 -> Test read /test_2k.bin
08:55:45.916 -> Read file used: 5182 ms, 809.398682 KB/s
08:55:45.949 -> Test read /test_4k.bin
08:55:51.091 -> Read file used: 5162 ms, 812.534668 KB/s
08:55:51.091 -> Test read /test_8k.bin
08:55:56.257 -> Read file used: 5177 ms, 810.180420 KB/s
08:55:56.293 -> Test read /test_16k.bin
08:56:01.244 -> Read file used: 4956 ms, 846.308289 KB/s
08:56:01.244 -> Test read /test_32k.bin
08:56:06.006 -> Read file used: 4764 ms, 880.416443 KB/s
08:56:06.006 -> Test read /test_64k.bin
08:56:10.716 -> Read file used: 4728 ms, 887.120117 KB/s

Old 128 MB MicroSD

08:51:01.939 -> Test write /test_1k.bin
08:51:18.358 -> Write file used: 16422 ms, 255.407623 KB/s
08:51:18.358 -> Test write /test_2k.bin
08:51:34.529 -> Write file used: 16173 ms, 259.339874 KB/s
08:51:34.529 -> Test write /test_4k.bin
08:51:50.911 -> Write file used: 16372 ms, 256.187653 KB/s
08:51:50.911 -> Test write /test_8k.bin
08:52:07.056 -> Write file used: 16137 ms, 259.918457 KB/s
08:52:07.056 -> Test write /test_16k.bin
08:52:23.383 -> Write file used: 16351 ms, 256.516663 KB/s
08:52:23.383 -> Test write /test_32k.bin
08:52:39.533 -> Write file used: 16128 ms, 260.063507 KB/s
08:52:39.533 -> Test write /test_64k.bin
08:52:55.764 -> Write file used: 16250 ms, 258.111023 KB/s
08:52:55.764 -> Test read /test_1k.bin
08:53:00.645 -> Read file used: 4855 ms, 863.914307 KB/s
08:53:00.645 -> Test read /test_2k.bin
08:53:05.459 -> Read file used: 4839 ms, 866.770813 KB/s
08:53:05.459 -> Test read /test_4k.bin
08:53:10.306 -> Read file used: 4833 ms, 867.846863 KB/s
08:53:10.306 -> Test read /test_8k.bin
08:53:15.127 -> Read file used: 4827 ms, 868.925598 KB/s
08:53:15.127 -> Test read /test_16k.bin
08:53:19.963 -> Read file used: 4826 ms, 869.105652 KB/s
08:53:19.963 -> Test read /test_32k.bin
08:53:24.758 -> Read file used: 4824 ms, 869.466003 KB/s
08:53:24.792 -> Test read /test_64k.bin
08:53:29.592 -> Read file used: 4824 ms, 869.466003 KB/s

总结

4位SD总线模式有最好的性能,1位SD总线模式大约慢20%,SPI模式大约慢50%。其中一个主要原因是SD_MMC协议层没有实现任何类型的锁定,而SPI实现了。而且4位SD总线模式有双数据线,所以理论上速度加倍。但是我的旧MicroSD不支持4位SD总线模式。

  • 我推荐1位SD总线模式在大多数情况下,因为:

良好的性能
更好的SD卡兼容性
更宽松的SD上拉要求
只需要3个GPIO引脚
较小的代码配置
许多开发套件、开发板和转接板都可以使用该模式

  • 8
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
首先,您需要在ESP32上安装ESPAsyncWebServer库,该库允许您创建异步Web服务器。然后,您需要将SD卡插入ESP32,并通过SPI接口将其连接到ESP32。 以下是一个基本的示例代码,可以从SD卡读取文件并在Web浏览器中显示该文件的内容: ```c++ #include <SPI.h> #include <SD.h> #include <WiFi.h> #include <ESPAsyncWebServer.h> // Replace with your network credentials const char* ssid = "your_SSID"; const char* password = "your_PASSWORD"; // Initialize the server AsyncWebServer server(80); // Initialize the SD card #define SD_CS_PIN 5 File file; void setup(){ // Start Serial Monitor Serial.begin(115200); // Connect to Wi-Fi network with SSID and password Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } // Print local IP address and start web server Serial.println(WiFi.localIP()); server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ // Open file from SD card file = SD.open("/test.txt"); if(file){ // Read file content and send to client request->send(200, "text/plain", file.readString()); file.close(); } else{ request->send(404, "text/plain", "File not found"); } }); // Serve web requests server.begin(); } void loop(){ // Nothing to do here } ``` 在此示例中,我们将ESPAsyncWebServer库用于创建异步Web服务器。在设置过程中,我们连接到Wi-Fi网络并启动Web服务器。我们还通过SPI接口初始化SD卡,并在处理请求时从SD卡读取文件。 在此示例中,我们将文件名硬编码为“/test.txt”。您可以根据需要更改文件名。此外,如果尝试访问不存在的文件,则服务器将返回404错误。 请注意,此示例不是最安全的示例。在生产环境中,您需要使用SSL / TLS来保护Web服务器和客户端之间的通信,并对来自客户端的请求进行身份验证和授权。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值