Arduino+ESP32 之 SD卡讀寫
背景知識:
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 - IO12
、DAT3 - IO13
、CMD - IO15
、CLK - IO14
、DAT0 - IO2
、DAT1 - 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支援包以後,我們電腦本地已經有了,參考下面的路徑可以找到這些常式。
.