• [ESP32 Arduino]SD卡通过SPI的方式访问


    说明: 这是学习笔记,仅做分享用途, 其中会引用其他博文的内容,时间关系不能一一将引用的文章都列举出来,如有冒犯,还请见谅

    目录

    参考资料

    学习过程记录

    SD卡引脚定义图

     硬件原理图

     实验代码


    参考资料

    乐鑫官方文档非常的详细以及清晰, 在使用之前可以优先浏览一遍官方文档:

    SD/SDIO/MMC 驱动程序 - ESP32 - — ESP-IDF 编程指南 v4.4 文档 (espressif.com)

    以下博文可以参考:

    1. Arduino+ESP32 之 SD卡读写 - 一匹夫 - 博客园 (cnblogs.com)

    2. 玩转 ESP32 + Arduino (二十四) SD卡读写_finedayforu的博客-CSDN博客

    学习过程记录

    首要前提当然是把开发编译环境搭建好(这个需要自行研究,有时间我再整理一下):

    vscode+platformio框架

    platform: Arduino

    在学习过程中需要明确自己想要做什么, 此次目的是能够读写SD卡的数据.

    背景知识:

    ESP32有两种使用SD卡的方法,一种是使用SPI接口访问SD卡,另一种是使用SDMMC接口访问SD卡 。

    SD卡引脚定义图

     硬件原理图

    Arduino core for the ESP32中SPI方式占用4个IO口,SDMMC方式占用6个IO口,手上的这块板子设计好了SD卡的电路,需要清楚的是他使用的接线方式是怎样的:

    ESP32引脚图

    显然这里使用的是SPI的方式访问SD卡的,在后面的API使用的时候就要注意不要用到SDMMC的API了.

    SD卡引脚图

     实验代码

     pio中提供了API以及sample code:

    我们可以通过下面的位置查看SPI引脚是否和硬件是否一致,这有利于在出现问题的时候排查:

    _spi_num这个变量的默认值为HSPI, _sck会被赋值为SCK, 和原理图中使用的引脚相同

     SD_Test中有非常详细的API方法,运行一下看看现象:

    1. /*
    2. * Connect the SD card to the following pins:
    3. *
    4. * SD Card | ESP32
    5. * D2 -
    6. * D3 SS
    7. * CMD MOSI
    8. * VSS GND
    9. * VDD 3.3V
    10. * CLK SCK
    11. * VSS GND
    12. * D0 MISO
    13. * D1 -
    14. */
    15. #include "FS.h"
    16. #include "SD.h"
    17. #include "SPI.h"
    18. void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    19. Serial.printf("Listing directory: %s\n", dirname);
    20. File root = fs.open(dirname);
    21. if(!root){
    22. Serial.println("Failed to open directory");
    23. return;
    24. }
    25. if(!root.isDirectory()){
    26. Serial.println("Not a directory");
    27. return;
    28. }
    29. File file = root.openNextFile();
    30. while(file){
    31. if(file.isDirectory()){
    32. Serial.print(" DIR : ");
    33. Serial.println(file.name());
    34. if(levels){
    35. listDir(fs, file.path(), levels -1);
    36. }
    37. } else {
    38. Serial.print(" FILE: ");
    39. Serial.print(file.name());
    40. Serial.print(" SIZE: ");
    41. Serial.println(file.size());
    42. }
    43. file = root.openNextFile();
    44. }
    45. }
    46. void createDir(fs::FS &fs, const char * path){
    47. Serial.printf("Creating Dir: %s\n", path);
    48. if(fs.mkdir(path)){
    49. Serial.println("Dir created");
    50. } else {
    51. Serial.println("mkdir failed");
    52. }
    53. }
    54. void removeDir(fs::FS &fs, const char * path){
    55. Serial.printf("Removing Dir: %s\n", path);
    56. if(fs.rmdir(path)){
    57. Serial.println("Dir removed");
    58. } else {
    59. Serial.println("rmdir failed");
    60. }
    61. }
    62. void readFile(fs::FS &fs, const char * path){
    63. Serial.printf("Reading file: %s\n", path);
    64. File file = fs.open(path);
    65. if(!file){
    66. Serial.println("Failed to open file for reading");
    67. return;
    68. }
    69. Serial.print("Read from file: ");
    70. while(file.available()){
    71. Serial.write(file.read());
    72. }
    73. file.close();
    74. }
    75. void writeFile(fs::FS &fs, const char * path, const char * message){
    76. Serial.printf("Writing file: %s\n", path);
    77. File file = fs.open(path, FILE_WRITE);
    78. if(!file){
    79. Serial.println("Failed to open file for writing");
    80. return;
    81. }
    82. if(file.print(message)){
    83. Serial.println("File written");
    84. } else {
    85. Serial.println("Write failed");
    86. }
    87. file.close();
    88. }
    89. void appendFile(fs::FS &fs, const char * path, const char * message){
    90. Serial.printf("Appending to file: %s\n", path);
    91. File file = fs.open(path, FILE_APPEND);
    92. if(!file){
    93. Serial.println("Failed to open file for appending");
    94. return;
    95. }
    96. if(file.print(message)){
    97. Serial.println("Message appended");
    98. } else {
    99. Serial.println("Append failed");
    100. }
    101. file.close();
    102. }
    103. void renameFile(fs::FS &fs, const char * path1, const char * path2){
    104. Serial.printf("Renaming file %s to %s\n", path1, path2);
    105. if (fs.rename(path1, path2)) {
    106. Serial.println("File renamed");
    107. } else {
    108. Serial.println("Rename failed");
    109. }
    110. }
    111. void deleteFile(fs::FS &fs, const char * path){
    112. Serial.printf("Deleting file: %s\n", path);
    113. if(fs.remove(path)){
    114. Serial.println("File deleted");
    115. } else {
    116. Serial.println("Delete failed");
    117. }
    118. }
    119. void testFileIO(fs::FS &fs, const char * path){
    120. File file = fs.open(path);
    121. static uint8_t buf[512];
    122. size_t len = 0;
    123. uint32_t start = millis();
    124. uint32_t end = start;
    125. if(file){
    126. len = file.size();
    127. size_t flen = len;
    128. start = millis();
    129. while(len){
    130. size_t toRead = len;
    131. if(toRead > 512){
    132. toRead = 512;
    133. }
    134. file.read(buf, toRead);
    135. len -= toRead;
    136. }
    137. end = millis() - start;
    138. Serial.printf("%u bytes read for %u ms\n", flen, end);
    139. file.close();
    140. } else {
    141. Serial.println("Failed to open file for reading");
    142. }
    143. file = fs.open(path, FILE_WRITE);
    144. if(!file){
    145. Serial.println("Failed to open file for writing");
    146. return;
    147. }
    148. size_t i;
    149. start = millis();
    150. for(i=0; i<2048; i++){
    151. file.write(buf, 512);
    152. }
    153. end = millis() - start;
    154. Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
    155. file.close();
    156. }
    157. void setup(){
    158. Serial.begin(115200);
    159. if(!SD.begin()){
    160. Serial.println("Card Mount Failed");
    161. return;
    162. }
    163. uint8_t cardType = SD.cardType();
    164. if(cardType == CARD_NONE){
    165. Serial.println("No SD card attached");
    166. return;
    167. }
    168. Serial.print("SD Card Type: ");
    169. if(cardType == CARD_MMC){
    170. Serial.println("MMC");
    171. } else if(cardType == CARD_SD){
    172. Serial.println("SDSC");
    173. } else if(cardType == CARD_SDHC){
    174. Serial.println("SDHC");
    175. } else {
    176. Serial.println("UNKNOWN");
    177. }
    178. uint64_t cardSize = SD.cardSize() / (1024 * 1024);
    179. Serial.printf("SD Card Size: %lluMB\n", cardSize);
    180. listDir(SD, "/", 0);
    181. createDir(SD, "/mydir");
    182. listDir(SD, "/", 0);
    183. removeDir(SD, "/mydir");
    184. listDir(SD, "/", 2);
    185. writeFile(SD, "/hello.txt", "Hello ");
    186. appendFile(SD, "/hello.txt", "World!\n");
    187. readFile(SD, "/hello.txt");
    188. deleteFile(SD, "/foo.txt");
    189. renameFile(SD, "/hello.txt", "/foo.txt");
    190. readFile(SD, "/foo.txt");
    191. testFileIO(SD, "/test.txt");
    192. Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
    193. Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
    194. }
    195. void loop(){
    196. }

    列出了SD下所有文件目录,并且创建了对应的文件:

     

  • 相关阅读:
    Linux内核内存管理:详解虚拟地址空间-MMU
    91.(leaflet之家)leaflet态势标绘-进攻方向绘制
    Docker的使用
    使用Spring Boot限制在一分钟内某个IP只能访问10次
    Spring 框架学习(九)---- Spring 整合 Mybatis 框架
    [安卓app毕业设计源码]精品基于Uniapp+SSM实现的家庭客栈/民宿管理系统实现的App[包运行成功]
    pytest 的使用===谨记
    使用Java统计gitlab代码行数
    search——single list
    lua基础之io
  • 原文地址:https://blog.csdn.net/qq_38609565/article/details/126190990