Arduino+ESP32 之 SD卡讀寫

一匹夫發表於2022-02-01

背景知識:

ESP32有兩種使用SD卡的方法,一種是使用SPI介面訪問SD卡,另一種是使用SDMMC介面訪問SD卡 。

Arduino core for the ESP32中SPI方式佔用4個IO口,SDMMC方式佔用6個IO口,一般來說SDMMC方式速度要比SPI方式快。

 

1. SDMMC方式

ESP32雖然有兩組SDMMC介面,但Arduino core for the ESP32中只用到了其中一組,IO口連線為:DAT2 - IO12DAT3 - IO13CMD - IO15CLK - IO14DAT0 - IO2DAT1 - IO4

bool begin(const char * mountpoint="/sdcard", bool mode1bit=false)
掛載儲存卡,輸入引數分別為掛載點、是否使用一線模式;

void end()
取消掛載;

sdcard_type_t cardType()   返回儲存卡型別,0、1、2、3、4,分別如下:
CARD_NONE          未連線儲存卡;
CARD_MMC            mmc卡;
CARD_SD                sd卡,最大2G;
CARD_SDHC           sdhc卡,最大32G;
CARD_UNKNOWN  未知儲存卡;

uint64_t cardSize()      返回儲存卡大小位元組數;
uint64_t totalBytes()    返回檔案系統總位元組數;
uint64_t usedBytes()   返回檔案系統已用位元組數;

 

2. SPI方式

bool begin(uint8_t ssPin=SS, SPIClass &spi=SPI, uint32_t frequency=4000000, const char * mountpoint="/sd", uint8_t max_files=5)
掛載儲存卡,輸入引數分別為SS引腳號、SPI物件、時脈頻率、掛載點、檔案最大同時開啟數;
預設IO口連線為:CS - IO5、DI - IO23、SCLK - IO18、DO - IO19;
void end()
取消掛載;
sdcard_type_t cardType()    返回儲存卡型別,0、1、2、3、4,分別如下:
CARD_NONE         未連線儲存卡;
CARD_MMC           mmc卡;
CARD_SD               sd卡,最大2G;
CARD_SDHC          sdhc卡,最大32G;
CARD_UNKNOWN  未知儲存卡;
uint64_t cardSize()      返回儲存卡大小位元組數;
uint64_t totalBytes()     返回檔案系統總位元組數;
uint64_t usedBytes();   返回檔案系統已用位元組數

 

3. 我的實驗

我手頭的ESP32_CAM板子的原理圖

右圖可知,我的SD卡接到了ESP32的GPIO12 13 14 15 2 4 這6個腳上,根據前述,這符合SDMMC方式的IO連線。所以,我在軟體上需要使用SDMMC方式來驅動SD卡。

 

新建arduino專案檔案,複製黏貼如下程式碼,即可以SDMMC方式驅動SD卡

//引用相關庫
//#include "FS.h"
#include "SD_MMC.h"

// 介面連線如下:
// SD卡 - ESP32
// ------------
// DAT2 - IO12
// DAT3 - IO13
// CMD  - IO15
// CLK  - IO14
// DAT0 - IO2
// DAT1 - IO4

void setup()
{
  Serial.begin(115200);
  Serial.println();

  //掛載檔案系統
  if (!SD_MMC.begin())
  {
    Serial.println("儲存卡掛載失敗");
    return;
  }
  uint8_t cardType = SD_MMC.cardType();

  if (cardType == CARD_NONE)
  {
    Serial.println("未連線儲存卡");
    return;
  }
  else if (cardType == CARD_MMC)
  {
    Serial.println("掛載了MMC卡");
  }
  else if (cardType == CARD_SD)
  {
    Serial.println("掛載了SDSC卡");
  }
  else if (cardType == CARD_SDHC)
  {
    Serial.println("掛載了SDHC卡");
  }
  else
  {
    Serial.println("掛載了未知儲存卡");
  }

  //開啟/建立 並寫入資料
  File file = SD_MMC.open("/test.txt", FILE_WRITE);
  if (file)
  {
    Serial.println("開啟/建立 根目錄下 test.txt 檔案!");
  }

  char data[] = "hello world\r\n";
  file.write((uint8_t *)data, strlen(data));
  file.close();

  //重新命名檔案
  if (SD_MMC.rename("/test.txt", "/retest.txt"))
  {
    Serial.println("test.txt 重新命名為 retest.txt !");
  }

  //讀取檔案資料
  file = SD_MMC.open("/retest.txt", FILE_READ);
  if (file)
  {
    Serial.print("檔案內容是:");
    while (file.available())
    {
      Serial.print((char)file.read());
    }
  }

  //列印儲存卡資訊
  Serial.printf("儲存卡總大小是: %lluMB \n", SD_MMC.cardSize() / (1024 * 1024)); // "/ (1024 * 1024)"可以換成">> 20"
  Serial.printf("檔案系統總大小是: %lluB \n", SD_MMC.totalBytes());
  Serial.printf("檔案系統已用大小是: %lluB \n", SD_MMC.usedBytes());
}

void loop()
{
}

 

4. 實驗效果

 

5.補充,如果不追求讀寫SD卡的速率,那麼可以SPI方式來進行SD卡的讀寫,那麼這樣就可以省下ESP32寶貴的2個GPIO作其他用途。

其實,這些例程在我們安裝好Arduino的ESP32支援包以後,我們電腦本地已經有了,參考下面的路徑可以找到這些例程。

 

 

 

.

相關文章