• 正文
  • 相关推荐
申请入驻 产业图谱

ESP32:SD卡测试

22小时前
239
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

一、准备工作

将SD卡以FAT32或者FAT16的格式格式化。一开始式格式化为FAT32格式,但是电脑在SD卡新建的文件和文件夹读取不出来,具体什么原因还不清楚,格式化工具用的是SD Card Formatter。以下为FAT16格式化的SD测试。

二、测试内容

(1)读取SD文件及文件夹内的文件名,以树状图输出。

(2)文件写入测试。

(3)SD卡内存大小读取测试。

(4)速度测试。

三、程序

#include <SD.h>
#include <SPI.h>
#include <FS.h>  // 添加文件系统支持
 
#define SD_CS_PIN 5        // SD卡片选引脚
#define HSPI_SCK_PIN  14   // HSPI时钟引脚
#define HSPI_MISO_PIN 12   // HSPI MISO引脚
#define HSPI_MOSI_PIN 13   // HSPI MOSI引脚
 
SPIClass hspi(HSPI);       // 创建HSPI实例
 
void setup() {
  Serial.begin(115200);
  while (!Serial);         // 等待串口连接
 
  // 配置高速SPI
  hspi.begin(HSPI_SCK_PIN, HSPI_MISO_PIN, HSPI_MOSI_PIN, SD_CS_PIN);
  hspi.setFrequency(40000000);  // 设置SPI时钟为40MHz
 
  // 初始化SD卡
  if (!SD.begin(SD_CS_PIN, hspi)) {
    Serial.println("SD卡初始化失败!");
    while(1);  // 停止执行
  }
  Serial.println("\nSD卡初始化成功!");
 
  // 执行完整测试流程
  listAllFolders("/");
  testFolderOperations();
  testFileOperations();
  speedTest();
  sdCardInfo();  // 读取SD卡信息
}
 
void loop() {}
 
// 改进版目录遍历函数,输出树状图
void listAllFolders(const char *dirname) {
  static int depth = 0;  // 目录深度计数器
  String indent = String(depth * 2, ' ');  // 缩进格式
 
  // 打印目录名称
  Serial.printf("%s[%s]\n", indent.c_str(), dirname);
 
  File root = SD.open(dirname);
  if (!root) {
    // 目录无法打开时输出错误信息
    Serial.printf("%s 无法打开目录\n", indent.c_str());
    return;
  }
 
  if (!root.isDirectory()) {
    // 如果不是目录,输出错误信息
    Serial.printf("%s 不是有效目录\n", indent.c_str());
    root.close();
    return;
  }
 
  File file;
  while ((file = root.openNextFile())) {
    // 跳过系统文件和隐藏文件(以 "." 开头的文件)
    if (String(file.name()).indexOf("/.") >= 0) {
      file.close();
      continue;
    }
 
    if (file.isDirectory()) {
      // 打印目录
      Serial.printf("%s  ├─📁 %s\n", indent.c_str(), file.name());
      depth++;
      listAllFolders(file.name());  // 递归遍历子文件夹
      depth--;
    } else {
      // 打印文件
      Serial.printf("%s  ├─📄 %s (%d bytes)\n", 
                   indent.c_str(), file.name(), file.size());
    }
    file.close();
  }
  root.close();
}
 
// 文件夹操作测试
void testFolderOperations() {
  const char* testDir = "/arduino_test";
  
  Serial.println("\n=== 文件夹操作测试 ===");
  
  // 删除旧测试目录(如果存在)
  if (SD.exists(testDir)) {
    SD.rmdir(testDir);
    Serial.println("已清理旧测试目录");
  }
 
  // 创建新目录
  if (SD.mkdir(testDir)) {
    Serial.printf("创建目录成功: %s\n", testDir);
  } else {
    Serial.printf("创建目录失败: %s\n", testDir);
    return;
  }
 
  // 验证目录存在
  if (SD.exists(testDir)) {
    Serial.println("目录验证通过");
  } else {
    Serial.println("目录验证失败");
  }
}
 
// 文件操作测试
void testFileOperations() {
  const char* testFile = "/arduino_test/test.txt";
  
  Serial.println("\n=== 文件操作测试 ===");
 
  // 写入文件
  File file = SD.open(testFile, FILE_WRITE);
  if (file) {
    file.println("=== 测试文件内容 ===");
    file.println("时间戳: " + String(millis()));
    file.close();
    Serial.printf("文件写入成功: %s\n", testFile);
  } else {
    Serial.printf("文件创建失败: %s\n", testFile);
    return;
  }
 
  // 读取文件
  file = SD.open(testFile);
  if (file) {
    Serial.println("文件内容:");
    while (file.available()) {
      Serial.write(file.read());
    }
    file.close();
  } else {
    Serial.println("文件读取失败");
  }
}
 
// 速度测试(改进版)
void speedTest() {
  const char* testFile = "/speed_test.bin";
  const size_t fileSize = 2 * 1024 * 1024;  // 2MB测试文件
  uint8_t buffer[512];  // 512字节缓冲区
  
  Serial.println("\n=== 速度测试 ===");
 
  // 写入速度测试
  SD.remove(testFile);
  File file = SD.open(testFile, FILE_WRITE);
  if (!file) {
    Serial.println("创建测试文件失败");
    return;
  }
 
  Serial.println("开始写入测试...");
  unsigned long start = millis();
  for (size_t i = 0; i < fileSize / sizeof(buffer); i++) {
    if (i % 100 == 0) Serial.print(".");
    file.write(buffer, sizeof(buffer));
  }
  file.close();
  unsigned long writeTime = millis() - start;
 
  // 读取速度测试
  file = SD.open(testFile);
  if (!file) {
    Serial.println("打开测试文件失败");
    return;
  }
 
  Serial.println("\n开始读取测试...");
  start = millis();
  while (file.available()) {
    file.read(buffer, sizeof(buffer));
  }
  file.close();
  unsigned long readTime = millis() - start;
 
  // 显示结果
  Serial.println("\n测试结果:");
  Serial.printf("文件大小: %.2f MB\n", fileSize / 1024.0 / 1024.0);
  Serial.printf("写入时间: %lu ms | 速度: %.2f KB/s\n", 
               writeTime, (fileSize / 1024.0) / (writeTime / 1000.0));
  Serial.printf("读取时间: %lu ms | 速度: %.2f KB/s\n", 
               readTime, (fileSize / 1024.0) / (readTime / 1000.0));
 
  SD.remove(testFile);
}
 
// 读取SD卡信息
void sdCardInfo() {
  Serial.println("\n=== SD卡信息 ===");
 
  uint64_t cardSize = SD.cardSize() / (1024 * 1024);  // 卡的总大小(MB)
  uint64_t usedSpace = SD.usedBytes() / (1024 * 1024);  // 已用空间(MB)
  uint64_t freeSpace = SD.totalBytes() / (1024 * 1024) - usedSpace;  // 可用空间(MB)
 
  Serial.printf("总大小: %llu MB\n", cardSize);
  Serial.printf("可用空间: %llu MB\n", freeSpace);
  Serial.printf("已用空间: %llu MB\n", usedSpace);
}

四、输出

SD卡初始化成功!
0[/]
0  ├─📁 System Volume Information
2[System Volume Information]
2 无法打开目录
0  ├─📁 arduino_test
2[arduino_test]
2 无法打开目录
0  ├─📁 testFile
2[testFile]
2 无法打开目录
0  ├─📁 testFile2
2[testFile2]
2 无法打开目录
0  ├─📁 testFile3
2[testFile3]
2 无法打开目录
0  ├─📁 testFile4
2[testFile4]
2 无法打开目录
=== 文件夹操作测试 ===
已清理旧测试目录
创建目录成功: /arduino_test
目录验证通过
=== 文件操作测试 ===
文件写入成功: /arduino_test/test.txt
文件内容:
=== 测试文件内容 ===
时间戳: 169
=== 速度测试 ===
开始写入测试...
.........................................
开始读取测试...
测试结果:
文件大小: 2.00 MB
写入时间: 4930 ms | 速度: 415.42 KB/s
读取时间: 4737 ms | 速度: 432.34 KB/s
=== SD卡信息 ===
总大小: 124 MB
可用空间: 123 MB
已用空间: 0 MB

 

相关推荐