一、准备工作
将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
阅读全文
239