SD 卡实验

罗大富 BigRich大约 9 分钟ESP32Arduino

这节课我们学习如何使用 MicroPython 控制 SD 卡模块。

实验原理

SD卡(Secure Digital Card)是一种常见的可移动存储设备,用于存储和传输数据。它是一种闪存存储卡,具有较小的尺寸、高存储容量和可擦写的特性。

SD 卡具有以下主要特点:

  • 尺寸小:SD 卡采用了较小的尺寸,便于携带和使用。标准尺寸的 SD 卡尺寸为 32mm × 24mm × 2.1mm,而微型 SD 卡和迷你 SD 卡则更小。
  • 高存储容量:SD 卡的存储容量可以从几百兆字节到数百千兆字节不等。现代的 SD 卡通常具有较大的存储容量,可以满足各种数据存储需求。
  • 可擦写性:SD 卡可以被多次擦写和重新写入,使其非常适合存储和传输数据。用户可以根据需要将数据写入 SD 卡,并随时进行修改或删除。
  • 高速传输:SD 卡支持高速数据传输,以满足对快速读写速度的需求。不同类型的 SD 卡可能具有不同的传输速度标准,例如 SDSC、SDHC 和 SDXC 等。
  • 兼容性:SD 卡具有广泛的兼容性,可以在许多设备上使用,例如数字相机、移动电话、音频播放器、电脑等。通过适配器,SD 卡还可以与其他类型的存储设备接口兼容。

SD 卡通常用于存储照片、音频、视频、文档和其他文件。它们广泛应用于数码相机、移动设备、嵌入式系统和各种消费电子产品中。在使用 SD 卡时,需要注意保护数据的安全性和完整性,避免数据丢失或损坏。

把 SD 卡通过读卡器连接到电脑,右击 SD 卡选择 格式化 选项,之后,我们可以看到 文件系统 选项,如下图

SD 卡使用的文件系统是指在 SD 卡上组织和管理文件和文件夹的方法。常见的 SD 卡文件系统有 FAT16、FAT32 和 exFAT 等。

  • FAT16(File Allocation Table 16):FAT16 是一种较早的文件系统,支持最大容量为 2GB 的存储设备。它使用 16 位的文件分配表来记录文件的存储位置和状态。FAT16 文件系统有一定的局限性,无法处理大容量存储设备和单个文件超过 2GB 的情况。
  • FAT32(File Allocation Table 32):FAT32 是一种较为常见的文件系统,支持最大容量为 2TB 的存储设备。它采用 32 位的文件分配表,可以更有效地管理存储空间和文件索引。FAT32 文件系统被广泛用于移动存储设备、数码相机和其他消费电子设备。
  • exFAT(Extended File Allocation Table):exFAT 是一种针对大容量存储设备设计的文件系统。它支持最大容量为 128PB 的存储设备和单个文件大小为 16EB 。exFAT 文件系统在支持大容量和大文件的同时,还具有较好的兼容性,可以在 Windows、Mac 和 Linux 等多个操作系统上使用。

SD 卡文件系统负责管理文件和目录的存储和访问。它使用文件分配表来记录文件的物理位置和状态,以及目录结构来组织文件和子目录。通过文件系统,用户可以方便地创建、读取、写入和删除文件,实现对存储设备中数据的管理和访问。

在使用 SD 卡时,需要选择适合的文件系统,根据存储设备的容量和应用需求进行设置。同时,还需要注意在使用过程中正确地操作文件系统,避免数据损坏和文件丢失的风险。

需要注意的是,在 SD 卡的文件系统选项中,存在 NTFS 选项,这个并不是 SD 卡的文件系统,如果你使用该选项格式化 SD 卡,会导致 SD 卡模块读取不到内容。

NTFS(New Technology File System) 是一种现代的文件系统,最早由微软引入并用于 Windows NT 操作系统及其后续版本。它具有许多先进的功能和优势,适用于处理大容量磁盘驱动器和大文件。

以下是 NTFS 的一些特点:

  • 支持大容量存储:NTFS 支持非常大的磁盘容量,可以处理多 TB 级别的存储设备。
  • 高性能:NTFS 采用了先进的索引结构和数据组织方式,具有快速读取和写入文件的能力,可以提供较高的数据访问性能。
  • 安全性:NTFS 支持文件和文件夹级别的访问控制,可以设置权限和加密保护,保障数据的安全性。
  • 容错能力:NTFS 具有容错和恢复功能,可以自动修复文件系统错误和数据损坏,并提供一致性和完整性保护。
  • 支持大文件:NTFS 支持单个文件的最大大小为 16EB(1EB = 1024PB),可以处理非常大的文件。
  • 支持文件压缩和加密:NTFS 提供了文件压缩和加密的功能,可以节省存储空间并保护敏感数据的安全性。

NTFS 是在 Windows 操作系统中广泛使用的文件系统,适合用于处理大容量存储和大文件的场景。它在性能、安全性和功能方面都有一定的优势,可以满足现代计算机系统对文件系统的要求。

接着我们来了解一下 SD 卡模块,SD 卡模块通过标准的 SPI 协议与单片机进行连接,如果我们采用双线或者三线 SPI 协议就无法实现全双工的数据读写功能。唯一需要注意的是 SD 卡模块的 VCC 接 5V 电源引脚。

硬件电路设计

物料清单(BOM 表):

材料名称数量
SD 卡模块1
SD 卡1
杜邦线(跳线)若干
面包板1

软件程序设计

在 Arduino 中对 SD 卡进行操作,可以使用 ESP32 自带的 SD 库。SD 库提供了一系列函数用于在 SD 卡上进行文件操作。下面是 SD 库中的一些常用函数的详细说明:

  1. SD.begin(uint8_t ssPin=SS, SPIClass &spi=SPI, uint32_t frequency=4000000, const char * mountpoint="/sd", uint8_t max_files=5, bool format_if_empty=false):初始化 SD 卡。此函数用于初始化 SD 卡并启动 SPI 通信。使用硬件 SPI,参数可以不填,使用默认参数即可。例如:SD.begin()
  2. open():打开一个文件,并返回一个 File 对象,以便进行后续的文件操作。它接受两个参数,第一个是文件路径,第二个是文件打开模式。常见的打开模式包括 FILE_READ(只读)FILE_WRITE(只写)FILE_APPEND(追加写入)等。
  3. available():检查文件是否可用(即是否已经打开),如果文件可用,则返回 true,否则返回 false。
  4. read():读取文件内容,从文件中读取一个字节的数据,并返回读取到的数据。
  5. write():写入文件内容。它接受一个参数,即要写入的数据。
  6. println():写入一行数据。此函数与 write() 类似,但它会在写入数据后自动换行。
  7. close():关闭文件,释放 SD 卡的资源,结束 SD 卡的使用。
  8. remove():删除指定的文件。它接受一个参数,即要删除的文件路径。
  9. exists():检查指定路径的文件是否存在。如果文件存在,则返回 true,否则返回 false。
  10. mkdir():创建指定路径的目录。
  11. openNextFile():打开 SD 卡中的下一个文件。返回一个 File 对象,表示打开的文件。如果没有更多文件可打开,则返回一个空的 File 对象。
  12. name():获取打开文件的文件名。返回一个 char 类型的指针,指向文件名的字符串。
  13. isDirectory():检查打开的文件是否是一个目录。如果文件是一个目录,则返回 true;否则返回 false。

这些函数可以帮助你在 SD 卡上进行文件操作。使用 openNextFile() 函数,你可以迭代打开 SD 卡中的每个文件。使用 name() 函数,你可以获取打开文件的文件名。使用 isDirectory() 函数,你可以判断文件是一个目录还是一个普通文件。这些函数的组合可以帮助你遍历 SD 卡上的文件,并执行相应的操作。

以上是 SD 库中的一些常用函数,你可以根据具体的应用需求选择适合的函数来进行 SD 卡上的文件操作。你可以参考 SD 库的官方文档和示例代码以了解更多函数和用法。

因此,我们对 SD 卡中的文件进行读写操作的代码可以这么写:

#include <SD.h>


// 初始化文件对象
File my_file;


void setup() {
  Serial.begin(9600);
  
  if (!SD.begin()) {
    Serial.println("SD卡初始化失败");
    return;
  }

  Serial.println("SD卡初始化成功");

  // 读取文件列表
  list_files("/");

  // 创建一个新的文件并写入数据
  my_file = SD.open("/test.txt", FILE_WRITE); 

  if (my_file) {
    my_file.println("你好,SD 卡"); // 写入数据
    my_file.close(); // 关闭文件
    Serial.println("数据写入完成");
  } else {
    Serial.println("无法打开文件");
  }

  delay(1000);

  // 读取文件内容
  my_file = SD.open("/test.txt");
  while (my_file.available()) {
      Serial.write(my_file.read());
    }
  my_file.close();
  Serial.println("\n文件读取完成");

  delay(1000);

  // 修改文件内容
  my_file = SD.open("/test.txt", FILE_APPEND);
  my_file.println("修改文件");
  my_file.close();
  Serial.println("文件修改成功");

  delay(1000);

  // 读取文件内容
  Serial.println("读取文件内容");
  my_file = SD.open("/test.txt");
  while (my_file.available()) {
      Serial.write(my_file.read());
    }
  my_file.close();
  Serial.println("\n文件读取完成");

  delay(1000);

  // 删除文件
  if (SD.remove("/test.txt")) {
    Serial.println("文件删除成功");
  } else {
    Serial.println("文件删除失败");
  }

  // 读取文件列表
  list_files("/");
}

void loop() {
  // 在这里进行其他操作
}


// 读取文件列表
void list_files(const char* path) {
  Serial.println("文件列表:");

  File root = SD.open(path);

  File file = root.openNextFile();
  while (file) {
    if (file.isDirectory()) {
      Serial.print("目录:");
    } else {
      Serial.print("文件:");
    }
    Serial.println(file.name());

    file = root.openNextFile();
  }
  root.close();

}

为什么文件列表中存在 System Volume Information?

System Volume Information是 Windows 操作系统在存储设备上创建的隐藏文件夹,用于存储系统恢复信息和其他系统相关数据。当你在 Windows 中使用 SD 卡时,它会在 SD 卡的根目录下创建这个文件夹。

需要注意的是,使用 ESP32 自带的 SD 库时,在我们读取文件列表时,无法读取到中文名,因此,如果你想要读取到中文名的话,可以下载第三方库 SDFat

上次编辑于:
贡献者: Luo