ESP32 開發筆記(三)源碼示例 9_SPI_SDCard 使用SPI總線實現TF卡文件系統示例

開發板購買連接windows

https://item.taobao.com/item.htm?spm=a2oq0.12575281.0.0.50111deb2Ij1As&ft=t&id=626366733674app

開發板簡介
開發環境搭建 windows
源碼示例:
    0_Hello Bug (ESP_LOGX與printf)    工程模板/打印調試輸出
    1_LED                                                    LED亮滅控制       
    2_LED_Task                                          使用任務方式控制LED
    3_LEDC_PWM                                      使用LEDC來控制LED實現呼吸燈效果
    4_ADC_LightR                                      使用ADC讀取光敏電阻實現光照傳感
    5_KEY_Short_Long                              按鈕長按短按實現
    6_TouchPad_Interrupt                          電容觸摸中斷實現
    7_WS2812_RMT                                  RGB_LED彩虹變色示例
    8_DHT11_RMT                                    使用RMT實現讀取DHT11溫溼度傳感器
    9_SPI_SDCard                                    使用SPI總線實現TF卡文件系統示例
    10_IIC_ADXL345                                使用IIC總線實現讀取ADXL345角度加速度傳感器
    11_IIC_AT24C02                                 使用IIC總線實現小容量數據儲存測試
    12_IR_Rev_RMT                                使用RMT實現紅外遙控接收掃碼(NEC)
    13_IR_Send_RMT                              使用RMT實現紅外數據發送(NEC)
    14_WIFI_Scan                                    附近WIFI信號掃描示例    
    15_WIFI_AP                                        建立軟AP示例
    16_WIFI_AP_TCP_Server                  在軟AP模式下實現TCP服務端
    17_WIFI_AP_TCP_Client                   在軟AP模式下實現TCP客戶端
    18_WIFI_AP_UDP                              在軟AP模式下實現UDP通信
    19_WIFI_STA                                      建立STA站模
    20_WIFI_STA_TCP_Server                在站模式STA下實現TCP服務端
    21_WIFI_STA_TCP_Client                 在站模式STA下實現TCP客戶端
    22_WIFI_STA_UDP                            在站模式STA下實現UDP通信
    23_LVGL_Test                                     LVGL圖形庫簡單示例

























函數

Micro SD Card,原名Trans-flash Card(TF卡),2004年正式改名爲Micro SD Card,由SanDisk(閃迪)公司發明,主要用於移動電話。
在Micro SD面市以前,手機制造商都採用嵌入式記憶體,雖然這類模組容易裝設,然而有着沒法應實際應潮流需求的困擾——容量被限制住了,沒法再有升級空間。Micro SD仿效SIM卡的應用模式,便是同一張卡能夠應用在不一樣型號的行動電話內,讓行動電話製造商不用再爲插卡式的研發設計而傷腦筋。 Micro SD卡足以堪稱可移動式的儲存IC。
Micro SD卡是一種極細小的快閃存儲器卡,其格式源自SanDisk創造,本來這種記憶卡稱爲T-Flash,及後改稱爲Trans Flash;而從新命名爲Micro SD的緣由是由於被SD協會 (SDA) 採立。另外一些被SDA採立的記憶卡包括Mini SD和SD卡。其主要應用於移動電話,但因它的體積微小和儲存容量的不斷提升,已經使用於GPS設備、便攜式音樂播放器和一些快閃存儲器盤中。它的體積爲 15mm x 11mm x1mm ,差很少相等於手指甲的大小,是現時最細小的記憶卡。它也能經過SD轉接卡來接駁於SD卡插槽中使用。 現時MicroSD卡提供128MB、256MB、512MB、1G、2G、4G、8G、16G、32G、64G、128G的容量(MWC 2014 世界移動通訊大會期間,SanDisk(閃迪)打破了儲存卡最高64GB容量的傳統,正式發佈了一款容量高達128GB的 Micro SD XC 儲存卡。

測試

SD卡的操做模式:SD卡模式(SDIO)、SPI模式(默認爲SD模式)。ui

其中SD卡模式的信號線有:CLK、CMD、DAT0-DAT3,6根線。spa

SPI模式的信號線有:CS、CLK、MISO(DATAOUT)、MOSI(DATAIN),4根線。.net

SDIO

  1. CLK 時鐘同步線
  2. CMD 命令信號線,主機發出的命令以及從機對命令的響應都是經過這條線進行傳輸
  3. DAT[3:0] 表示4條數據線,主機和從機的數據都是從這四條數據線上傳輸

SPI

SD卡只能使用3.3V的I/O電平。SPI模式下信號線要加10-100K的上拉電阻。設計

SD卡有五個寄存器:指針

名稱 寬度 描述
CID 128 卡標識寄存器
RCA 16 相對地址寄存器(Relative Card Address):本地系統中卡的地址,動態變化,在主機初始化的時候肯定,SPI模式中沒有。
CSD 128 卡描述數據:卡操做條件相關的信息數據
SCR 64 SD配置寄存器:SD卡特定信息數據
OCR 32 操做條件寄存器

SD卡的命令格式:調試

命令CMD0就是0,CMD16就是16,以此類推。

SPI命令格式爲6字節構成,高位在前(MSB)。

字節1 字節2-5 字節6
7 6 5-0
0 1 command

字節1的最高2位固定是01,低6位爲命令號(CMD0就是0,CMD16就是16,以此類推),字節2-5爲命令參數,有些命令是沒有參數的;字節6的高7位爲CRC,最低位恆爲1。

SD卡的命令總共有12類,下表爲幾個比較重要的命令:
SD卡的主要相關各類命令解析
CMD0: SD卡進入IDLE和復位SD卡
CMD1: 讀OCR,是否爲SD卡
CMD2: 獲取卡CID信息
CMD3: 獲取SD卡所分配的相對地址
CMD9: 獲取SD卡的存儲信息(容量、塊大小等)
CMD12:中止傳輸操做
CMD13:獲取卡的狀態
CMD16:設置SD卡塊大小
CMD17:使SD卡進入傳輸狀態、讀取單個塊
CMD18: 使SD卡進入傳輸狀態、讀取多個塊,直到收到CMD12爲止
CMD24:使SD卡進入傳輸狀態、寫入單個塊
CMD25: 使SD卡進入傳輸狀態、寫入多個塊












命令 參數 迴應 描述
CMD0(0X00) NONE R1 復位SD卡
CMD8(0X08) VHS+Check Pattern R7 發送接口狀態命令
CMD9(0X09) NONE R1 讀取卡特定數據寄存器
CMD10(0X0A) NONE R1 讀取卡標誌數據寄存器
CMD16(0X10) 塊大小 R1 設置塊大小(字節數)
CMD17(0X11) 地址 R1 讀取一個塊的數據
CMD24(0X18) 地址 R1 寫入一個塊的數據
CMD41(0X29) NONE R3 發送給主機容量支持信息和激活卡初始化過程
CMD55(0X37) NONE R1 告訴SD卡,下一個是特定應用命令
CMD58(0X3A) NONE R3 讀取OCR寄存器

SD卡和單片機的通訊採用發送應答機制:

發送應答機制

 

ESP32 FAT 文件系統

ESP-IDF 使用 FatFs 庫來實現 FAT 文件系統。FatFs 庫位於 fatfs 組件中,您能夠直接使用,也能夠藉助 C 標準庫和 POSIX API 經過 VFS(虛擬文件系統)使用 FatFs 庫的大多數功能。

此外,對 FatFs 庫進行了擴展,新增了支持可插拔磁盤 I/O 調度層,從而容許在運行時將 FatFs 驅動映射到物理磁盤。

FatFs 與 VFS 配合使用

函數 esp_vfs_fat_register() 分配一個 FATFS 結構,並在 VFS 中註冊特定路徑前綴。若是文件路徑以此前綴開頭,則對此文件的後續操做將轉至 FatFs API。函數 esp_vfs_fat_unregister_path() 刪除在 VFS 中的註冊,並釋放 FATFS 結構。

多數應用程序在使用 esp_vfs_fat_ 函數時,採用以下步驟:

調用 esp_vfs_fat_register(),指定:

      掛載文件系統的路徑前綴(例如,"/sdcard" 或 "/spiflash")
      FatFs 驅動編號
      一個用於接收指向 FATFS 結構指針的變量

調用 ff_diskio_register() 爲上述步驟中的驅動編號註冊磁盤 I/O 驅動;
調用 FatFs 函數 f_mount,或 f_fdisk, f_mkfs,並使用與傳遞到 esp_vfs_fat_register() 相同的驅動編號掛載文件系統。請參考 FatFs 文檔,
調用 C 標準庫和 POSIX API 對路徑中帶有步驟 1 中所述前綴的文件(例如,"/sdcard/hello.txt")執行打開、讀取、寫入、擦除、複製等操做。
您能夠選擇直接調用 FatFs 庫函數,但須要使用沒有 VFS 前綴的路徑(例如,"/hello.txt");
關閉全部打開的文件;
調用 f_mount 並使用 NULL FATFS* 參數爲與上述編號相同的驅動卸載文件系統;
調用 FatFs 函數 ff_diskio_register() 並使用 NULL ff_diskio_impl_t* 參數和相同的驅動編號來釋放註冊的磁盤 I/O 驅動。
調用 esp_vfs_fat_unregister_path() 並使用文件系統掛載的路徑將 FatFs 從 NVS 中移除,並釋放步驟 1 中分配的 FatFs 結構。
esp_vfs_fat_sdmmc_mount 和 esp_vfs_fat_sdmmc_unmount 這兩個便捷函數對上述步驟進行了封裝,並加入對 SD 卡初始化的處理,很是便捷。







1、硬件設計/原理

查看開發板原理圖,TF卡使用SPI總線鏈接到ESP32主控,對信號線進行10K上拉。

2、程序設計

先引用必要頭文件

// SD card and FAT filesystem example

#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_vfs_fat.h"
#include "driver/sdspi_host.h"
#include "driver/spi_common.h"
#include "sdmmc_cmd.h"
#include "sdkconfig.h"

定義SPI總線GPIO

static const char *TAG = "TF Card Fat Example";
#define MOUNT_POINT "/sdcard"
#define SPI_DMA_CHAN    1

//在測試SD和SPI模式時,請記住,一旦在SPI模式下初始化了卡,在不接通卡電源的狀況下就沒法在SD模式下將其從新初始化。
#define PIN_NUM_MISO		19
#define PIN_NUM_MOSI		23
#define PIN_NUM_CLK			18
#define PIN_NUM_CS			5

主函數,測試文件系統,讀取,寫入、獲取總容量、卡信息、剩餘容量、改名、刪除等操做

void app_main(void)
{
	esp_err_t ret;								// ESP錯誤定義
	sdmmc_card_t* card;							// SD / MMC卡信息結構
	const char mount_point[] = MOUNT_POINT;		// 根目錄
	char ReadFileBuff[64];

	esp_vfs_fat_sdmmc_mount_config_t mount_config = {	// 文件系統掛載配置
		.format_if_mount_failed = false,				// 若是掛載失敗:true會從新分區和格式化/false不會從新分區和格式化
		.max_files = 5,									// 打開文件最大數量
		.allocation_unit_size = 16 * 1024
	};

	printf("%s->Initializing SD card\r\n",TAG);
	printf("%s->Using SPI peripheralr\r\n",TAG);
	sdmmc_host_t host = SDSPI_HOST_DEFAULT();
	spi_bus_config_t bus_cfg = {
		.mosi_io_num = PIN_NUM_MOSI,
		.miso_io_num = PIN_NUM_MISO,
		.sclk_io_num = PIN_NUM_CLK,
		.quadwp_io_num = -1,
		.quadhd_io_num = -1,
		.max_transfer_sz = 4000,
	};
	// SPI總線初始化
	ret = spi_bus_initialize(host.slot, &bus_cfg, SPI_DMA_CHAN);
	if (ret != ESP_OK) {
		printf("%s->Failed to initialize bus.\r\n",TAG);
		return;
	}
	// 這將初始化沒有卡檢測(CD)和寫保護(WP)信號的插槽。
	// 若是您的主板有這些信號,請修改slot_config.gpio_cd和slot_config.gpio_wp。
	sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
	slot_config.gpio_cs = PIN_NUM_CS;
	slot_config.host_id = host.slot;
	// 掛載文件系統
	ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);
	if (ret != ESP_OK) {
		if (ret == ESP_FAIL) {
			printf("%s->Failed to mount filesystem.%s\r\n",TAG,
				"If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
		} else {
			printf("%s->Failed to initialize the card %s  (%s). ",TAG,
				"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
		}
		return;
	}
	// TF卡已經初始化,打印TF卡屬性
	sdmmc_card_print_info(stdout, card);

    // Print FAT FS size information
    size_t bytes_total, bytes_free;
    get_fatfs_usage(&bytes_total, &bytes_free);
    printf("%s->FAT FS Total: %d MB, Free: %d MB \r\n",TAG, bytes_total / 1024, bytes_free / 1024);


	// 使用POSIX和C標準庫函數來處理文件。
	printf("%s->Opening file\r\n",TAG);
	FILE* f = fopen(MOUNT_POINT"/hello.txt", "w");// 建立一個文件
	if (f == NULL) {
		printf("%s->Failed to open file for writing\r\n",TAG);
		return;
	}
	fprintf(f, "Hello %s!\n", card->cid.name);
	fclose(f);
	printf("%s->File written\r\n",TAG);

	// 重命名前檢查目標文件是否存在
	struct stat st;
	if (stat(MOUNT_POINT"/foo.txt", &st) == 0) {
		unlink(MOUNT_POINT"/foo.txt");// 刪除(若是存在)
	}

	// 重命名文件
	printf("%s->Renaming file\r\n",TAG);
	if (rename(MOUNT_POINT"/hello.txt", MOUNT_POINT"/foo.txt") != 0) {
		printf("%s->Rename failed\r\n",TAG);
		return;
	}

	// 讀取文件
	printf("%s->Reading file\r\n",TAG);
	f = fopen(MOUNT_POINT"/foo.txt", "r");// 讀取方式打開文件
	if (f == NULL) {
		printf("%s->Failed to open file for reading\r\n",TAG);
		return;
	}
	fgets(ReadFileBuff, sizeof(ReadFileBuff), f);	// 讀取一行數據
	fclose(f);										// 關閉文件 
	char* pos = strchr(ReadFileBuff, '\n');			// 在字符串中查找換行
	if (pos) {
		*pos = '\0';								// 替換爲結束符
	}
	printf("%s->Read from file: '%s'\r\n",TAG,ReadFileBuff);

	// 卸載分區並禁用SDMMC或SPI外設
	esp_vfs_fat_sdcard_unmount(mount_point, card);
	printf("%s->Card unmounted\r\n",TAG);
	//卸載總線
	spi_bus_free(host.slot);
}

3、下載測試

打開ESP-IDF Command Prompt

cd命令進入此工程目錄

cd F:\ESP32_DevBoard_File\9_SPI_SDCard

查看電腦設備管理器中開發板的串口號

執行idf.py -p COM9 flash monitor從串口9下載並運行打開口顯示設備調試信息   Ctrl+c退出運行,查看串口信息輸出

測試卡爲16G閃迪 class 10 TF卡

相關文章
相關標籤/搜索