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

本代码实现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.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;
  }
}


完整代码如下:

#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()
{

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/566161.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

系统安全与应用(1)

目录 1、账号安全管理 &#xff08;1&#xff09;禁止程序用户登录 &#xff08;2&#xff09;锁定禁用长期不使用的用户 &#xff08;3&#xff09;删除无用的账号 &#xff08;4&#xff09;禁止账号和密码的修改 2、密码安全管理 设置密码有效期 1&#xff09;针对已…

中颖51芯片学习9. PWM(12bit脉冲宽度调制)

中颖51芯片学习9. PWM&#xff08;12bit脉冲宽度调制&#xff09; 一、资源简介二、PWM工作流程三、寄存器介绍1. PWMx控制寄存器PWMxCON2. PWM0周期寄存器PWM0PH/L3. PWM1周期寄存器PWM1PH/L4. PWM0占空比控制寄存器PWM0DH/L5. PWM1占空比控制寄存器 PWM1DH/L6. 占空比寄存器与…

Next.js+React+Node系统实战,搞定SSR服务器渲染

Next.jsReactNode系统实战&#xff0c;搞定SSR服务器渲染 Next.js React Node.js 实战&#xff1a;实现服务器端渲染&#xff08;SSR&#xff09; 项目概述 在这个项目中&#xff0c;我们将探讨如何使用 Next.js、React 和 Node.js 来构建一个服务器渲染的 web 应用程序。通…

pytest使用 pytest-rerunfailures 插件实现失败用例重跑功能

使用 pytest 进行测试时&#xff0c;你可以通过安装并配置 pytest-rerunfailures 插件来实现失败用例重跑功能。以下是一个示例说明&#xff1a; 假设你有一个测试文件 test_example.py 包含如下测试用例&#xff1a; import pytestpytest.mark.parametrize("num",…

javaScript3

javaScript 一.对象1.概念2.创建对象的三种方法(1).字面量创建&#xff08;利用{}&#xff09;(2)变量、属性、函数、方法的区别(3).new Object创建(4).构造函数 3.new关键字的执行过程4.遍历对象&#xff08;for..in) 二.内置对象 一.对象 1.概念 一组无序的相关属性和方法的…

报错The chromedriver version cannot be discovered以及下载chromedriver.exe和查看其版本的命令

python3.8.10&#xff0c;win10。 谷歌浏览器版本&#xff08;我写代码的时候还是123.0.x.x&#xff0c;没几天就自动更新到124.0.x.x了&#xff09;&#xff1a; 在使用selenium的时候&#xff0c;出现报错&#xff0c;The chromedriver version cannot be discovered。 &am…

【面试八股总结】Linux系统下的I/O多路复用

参考资料 &#xff1a;小林Coding、阿秀、代码随想录 I/O多路复用是⼀种在单个线程或进程中处理多个输入和输出操作的机制。它允许单个进程同时监视多个文件描述符(通常是套接字)&#xff0c;一旦某个描述符就绪&#xff08;一般是读就绪或者写就绪&#xff09;&#xff0c;能够…

为什么iPhone支持整页中文OCR应用很少?有什么好的解决方法?

iPhone上面没有支持中文整页OCR识别的app&#xff0c;这是一个值得探讨的问题。OCR&#xff0c;即光学字符识别&#xff0c;是一种将纸质文档或图片中的文字转化为可编辑文本的技术。随着科技的发展&#xff0c;OCR技术已经广泛应用于各个领域&#xff0c;包括文档处理、图像识…

C/C++ 入门(7)string类(STL)

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;C 请多多指教&#xff01; 目录 一、标准库中的string 1、了解 2、string类常用接口说明 1、常见的构造函数 2、容量操作 ​编辑 3、访问及遍历操作 4、修改操作 5、非成员函数 二、string类实现 …

搭建知识库-DataWhale笔记

词向量及向量知识库介绍 词向量 词向量定义 在机器学习和自然语言处理&#xff08;NLP&#xff09;中&#xff0c;词向量&#xff08;Embeddings&#xff09;是一种将非结构化数据&#xff0c;如单词、句子或者整个文档&#xff0c;转化为实数向量的技术。这些实数向量可以被…

Unet网络架构讲解(从零到一,逐行编写并重点讲解数据维度变化)

&#x1f4da;博客主页&#xff1a;knighthood2001 ✨公众号&#xff1a;认知up吧 &#xff08;目前正在带领大家一起提升认知&#xff0c;感兴趣可以来围观一下&#xff09; &#x1f383;知识星球&#xff1a;【认知up吧|成长|副业】介绍 ❤️感谢大家点赞&#x1f44d;&…

大珩PPT助手一键颜色设置

大珩PPT助手最新推出的一键设置文字颜色和背景色功能&#xff0c;为用户在创建演示文稿时带来了更便捷、高效的体验。这一功能使用户能够轻松调整演示文稿中文字的颜色和幻灯片的背景色&#xff0c;以满足不同场合和主题的需要。 以下是该功能的几个关键特点和优势&#xff1a…

恶意游戏并非传说:它们甚至在 Steam 上也存在

三月份&#xff0c;玩家们在在线平台上遇到了热门游戏的假克隆。在受害者中&#xff0c;有一位用户购买了一款假冒游戏《最后纪元》&#xff08;Last Epoch&#xff09;&#xff0c;但玩了几个小时后却出现了 "蓝屏死机"。 在联系了技术支持后&#xff0c;Steam 将钱…

代码随想录算法训练营Day6 | 242.有效的字母异位词 ●349. 两个数组的交集 ● 202. 快乐数● 1. 两数之和

基础&#xff1a; 1.哈希表是根据关键值进行直接访问的数据结构&#xff0c;时间复杂度是O(1)&#xff0c;也就是通过数组的索引下标&#xff0c;直接访问数组中的元素哈希表的作用就是用来快速判断一个元素是否出现在集合里。 2.常见的哈希结构&#xff1a; 数组set &#…

CB2-2CARD之Debian(Bookworm)安装Gnome看CCTV

CB2-2CARD之Debian&#xff08;Bookworm&#xff09;安装Gnome看CCTV 1. 源由2. 需求3. Debian系统桌面3.1 系统安装3.2 磁盘扩容3.3 系统更新3.4 Gnome安装 4. 测试4.1 CCTV网页测试4.2 系统空闲测试4.3 Firefox CPU占用率测试 5. 总结 1. 源由 近些年来&#xff0c;随着国内…

arm架构,django4.2.7适配达梦8数据库

【Python相关包版本信息】 Django 4.2.7 django-dmPython 3.1.7 dmPython 2.5.5 【达梦数据库版本】 DM Database Server 64 V8 DB Version: 0x7000c 适配过程中发现的问题如下&#xff1a; 错误一&#xff1a;d…

Git | 分支管理

Git | 分支管理 文章目录 Git | 分支管理1、理解分支2、创建分支&&切换分支3、合并分支4、删除分支5、合并冲突6、分支管理策略合并分支模式实际工作中分支策略bug分支删除临时分支 1、理解分支 分支就类似分身。 在版本回退中&#xff0c;每次提交Git都会将修改以git…

快速部署stable diffusion@Ubuntu

Stable Diffusion可以根据文本描述生成相关的图像&#xff0c;是当前最热门的文生图模型。 在Ubuntu下&#xff0c;可以选择快速安装&#xff0c;或者手动一步步安装。 快速安装 使用文档中的方法&#xff0c;先下载一个sh文件&#xff0c;然后执行这个文件&#xff0c;就自动…

ChatGPT助力测试领域!探索人工智能编写测试用例的新前景

简介 测试用例是测试人员的核心工作内容&#xff0c;是测试人员思想的“实现类”&#xff0c;其充分体现了测试的思路&#xff0c;可以为后续的测试行为提供指导&#xff0c;是测试人员了解业务的重要根据和质量之根本。如果测试用例设计得不完成&#xff0c;出现了遗漏&#x…

git merge 和 git rebese的区别

git merge 和 git rebese的区别 拉取分支和合并代码会涉及两种选择&#xff0c;git merge 和 git rebase&#xff1a; rebase&#xff1a;变基&#xff0c;会有一个干净的分支&#xff0c;但是对于记录来源不够清楚merge&#xff1a;合并&#xff0c;git 分支看起来比较混乱&…