当前位置:   article > 正文

ESP32与SD卡交互实现:文件读写实战与初始化详解及引脚定义_esp32sd卡读写

esp32sd卡读写

本代码实现ESP32与SD卡的交互,包括定义SPI引脚、创建自定义SPI类实例、编写WriteFile与ReadFile函数进行文件读写。setup函数初始化串口、SPI、SD卡,向“/test.txt”写入“myfirstmessage”,读取并打印其内容。loop函数留空待扩展。

1. 需要准备的软硬件:

1.1 硬件:

  1. ESP32开发板在这里插入图片描述

  2. SD卡模块(如下图),可以是单独的TF卡模块也可以是集成到TFT屏幕的SD模块,TF卡与SD卡的硬件逻辑是一样,这主里不做区分在这里插入图片描述

  3. SD卡,Arduino 库仅支持 FAT16 和 FAT32 文件系统。 确保您的 SD 卡仅使用这两种格式进行格式化,否则将初始化错误。
    写本文时,在电脑上将SD卡以FAT32格式来格式化
    对于不同卡格式如下:

  • 对于SDSC卡:
    容量介于 16 MB 和 32 MB 之间 - FAT 16
    容量大于32 MB-FAT 16B
  • 对于SDHC卡
    容量小于 7.8 GB- FAT 32
    容量大于 7.8 GB- FAT 32
  • 对于SDXC卡
    exFAT

1.2 软件

  1. Arduino IDE或者在VS Code里的PlatformIO

1.3 连线方式一及代码

1.3.1 连接方式一如下表,本连线方式是用的ESP32的默认SPI接线方式,注意1.1的引脚图里23脚是VSPI MISO, 19脚是VSPI MOSI, 18脚是VSPI CLK 因此在接下来的代码中没有单独定义MISO、MOSI和CLK引脚。

引脚名称描述引脚编号
CSChip Select5
SCKClock18
MISOMaster In Slave Out19
MOSIMaster Out Slave In23

1.3.2 代码一:

/*
  SD Card Interface code for ESP32
  SPI Pins of ESP32 SD card as follows:
  CS    = 5;
  MOSI  = 23;
  MISO  = 19;
  SCK   = 18; 
*/

#include <SPI.h>
#include <SD.h>

File myFile;
const int CS = 5;

/**
 * @brief 将指定消息写入到文件中。
 * 
 * @param path 指向要写入的文件路径的字符指针。
 * @param message 指向要写入文件的消息的字符指针。
 * 该函数尝试打开指定路径的文件以进行写操作。如果文件成功打开,它将写入给定的消息,
 * 然后关闭文件,并通过串口打印一条完成消息。如果无法打开文件,它将打印错误消息和文件路径。
 */
void WriteFile(const char *path, const char *message){
  // 尝试打开文件以写入
  myFile = SD.open(path, FILE_WRITE);
  if (myFile) { // 文件打开成功
    Serial.printf("Writing to %s ", path); // 打印正在写入的文件路径
    myFile.println(message); // 写入消息到文件
    myFile.close(); // 关闭文件
    Serial.println("completed."); // 打印写入完成信息
  } 
  else { // 文件打开失败
    Serial.println("error opening file "); // 打印错误信息
    Serial.println(path); // 打印文件路径
  }
}

/**
 * 读取指定路径的文件
 * 
 * @param path 指向要打开的文件路径的字符指针
 * 
 * 该函数尝试打开指定路径的文件,如果成功打开,则逐字节读取文件内容并通过串口打印。
 * 如果无法打开文件,将打印错误信息。
 */
void ReadFile(const char *path){
  myFile = SD.open(path); // 尝试打开文件
  
  if (myFile) { // 如果文件成功打开
     Serial.printf("Reading file from %s\n", path); // 打印读取文件的路径信息
     while (myFile.available()) { // 循环,直到文件没有更多可用数据
      Serial.write(myFile.read()); // 读取并打印文件的一个字节
    }
    myFile.close(); // 关闭文件
  } 
  else {
    Serial.println("error opening test.txt"); // 如果无法打开文件,打印错误信息
  }
}

void setup() {
  Serial.begin(9600);
  delay(500);
  while (!Serial) { ; }
  Serial.println("Initializing SD card...");
  if (!SD.begin(CS)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  WriteFile("/test.txt", "ElectronicWings.com");
  ReadFile("/test.txt");
}

void loop() {
  // nothing happens after setup
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

1.4 连线方式二及代码

1.4.1 连接方式二如下表,本连线方式并没有使用ESP32默认的引脚,而是对SPI各个引脚进行了重定义

引脚名称描述引脚编号
CSChip Select23
SCKClock16
MISOMaster In Slave Out2
MOSIMaster Out Slave In17

1.4.2 代码二:

与代码一的主要不同只有下面几行:

const int MOSI_PIN = 17; // 定义SPI通信中MOSI(Master Out Slave In)信号的常量
const int MISO_PIN = 2; // 定义SPI通信中MISO(Master In Slave Out)信号的常量
const int SCK_PIN = 16; // 定义SPI通信中SCK(Serial Clock)信号的常量

// 定义一个自定义的SPI类实例
SPIClass CustomSPI;

void setup(){
  // 初始化自定义SPI通信,传入SCK、MISO、MOSI引脚及CS控制信号
  CustomSPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN, CS);

    // 初始化SD卡,如果初始化失败则打印错误信息并返回
  if (!SD.begin(CS, CustomSPI, 1000000))
  {
    Serial.println("initialization failed!");
    return;
  }
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

完整代码如下:

#include <Arduino.h>
/*
  SD Card Interface code for ESP32
  SPI Pins of ESP32 SD card as follows:
  CS    = 23;
  MOSI  = 17;
  MISO  = 2;
  SCK   = 16;
*/

#include <SPI.h>
#include <SD.h>

// 定义一个文件对象
File myFile; 

const int CS = 23; // 定义SPI通信中CS(Chip Select)信号的常量
const int MOSI_PIN = 17; // 定义SPI通信中MOSI(Master Out Slave In)信号的常量
const int MISO_PIN = 2; // 定义SPI通信中MISO(Master In Slave Out)信号的常量
const int SCK_PIN = 16; // 定义SPI通信中SCK(Serial Clock)信号的常量

// 定义一个自定义的SPI类实例
SPIClass CustomSPI;
/**
 * @brief 将指定消息写入到文件中。
 * 
 * @param path 指向要写入的文件路径的字符指针。
 * @param message 指向要写入文件的消息的字符指针。
 * 说明:函数不返回任何值,但会在串口打印操作的结果。
 */
void WriteFile(const char *path, const char *message)
{
  // 尝试打开文件以便写入
  myFile = SD.open(path, FILE_WRITE);
  if (myFile)
  {
    // 打印正在写入的文件路径
    Serial.printf("Writing to %s ", path);
    // 写入消息到文件,并在末尾添加换行符
    myFile.println(message);
    // 关闭文件
    myFile.close(); 
    // 打印写入操作完成的通知
    Serial.println("completed.");
  }

  else
  {
    // 打印打开文件失败的通知
    Serial.println("error opening file ");
    // 打印失败的文件路径
    Serial.println(path);
  }
}

/**
 * 读取指定路径的文件
 * 
 * @param path 指向要打开的文件路径的字符指针
 * 
 * 该函数尝试打开指定路径的文件,如果成功打开,则逐字节读取文件内容并通过串口打印。
 * 如果无法打开文件,将打印错误信息。
 */
void ReadFile(const char *path)
{
  myFile = SD.open(path); // 尝试打开文件
  
  if (myFile) // 如果文件成功打开
  {
    Serial.printf("Reading file from %s\n", path); // 打印读取文件的路径信息
    while (myFile.available()) // 循环读取文件中的所有内容
    {
      Serial.write(myFile.read()); // 将读取到的每个字节通过串口发送
    }
    myFile.close(); // 关闭文件
  }
  else // 如果文件打开失败
  {
    Serial.println("error opening test.txt"); // 打印错误信息
  }
}

/**
 * @brief 初始化设置函数
 * 该函数主要完成以下初始化工作:
 * 1. 初始化串口通信,设置波特率为9600;
 * 2. 初始化自定义SPI通信,并传入SCK、MISO、MOSI引脚及CS控制信号;
 * 3. 等待串口完全初始化;
 * 4. 初始化SD卡,如果初始化失败则打印错误信息并返回;
 * 5. 写入测试文件"/test.txt";
 * 6. 读取测试文件"/test.txt"的内容。
 * 
 * 该函数没有参数和返回值。
 */
void setup()
{
  // 初始化串口通信,设置波特率为9600,并延迟500ms
  Serial.begin(9600);
  delay(500);

  // 初始化自定义SPI通信,传入SCK、MISO、MOSI引脚及CS控制信号
  CustomSPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN, CS);

  // 等待直到串口完全初始化
  while (!Serial)
  {
    ;
  } 

  // 打印初始化SD卡的开始信息
  Serial.println("Initializing SD card...");
  
  // 初始化SD卡,如果初始化失败则打印错误信息并返回
  if (!SD.begin(CS, CustomSPI, 1000000))
  {
    Serial.println("initialization failed!");
    return;
  }
  
  // 打印SD卡初始化成功的消息
  Serial.println("initialization done.");

  // 写入测试文件"/test.txt"
  WriteFile("/test.txt", "myfirstmessage");
  
  // 读取测试文件"/test.txt"的内容
  ReadFile("/test.txt");
  //打印读取到的内容
  Serial.println("Reading from test.txt");

}

void loop()
{

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/794570
推荐阅读
相关标签
  

闽ICP备14008679号