使用STM32F103ZET6與TF卡連接,使用SPI通信方式外加FATFS文件系統(tǒng),親測可用。
FAT文件系統(tǒng)實驗
1. 了解 FAT 文件系統(tǒng) 2. 學(xué)會移植 FATFS 3. 學(xué)會使用 FATFS
我們學(xué)習(xí)了 SD 卡的使用,并且學(xué)會了怎么對 SD 卡進行讀寫操作,不過要 真正應(yīng)用 SD 卡,必須學(xué)習(xí)使用文件系統(tǒng)。什么是文件系統(tǒng)呢,操作系統(tǒng)用于明 確磁盤或分區(qū)上的文件的方法和數(shù)據(jù)結(jié)構(gòu),即在磁盤上組織文件的方法。我們電 腦的 windows 系統(tǒng)使用的就是 FAT 文件系統(tǒng),大家都知道,一般我們新買的 SD 卡,如果沒有使用過,插入電腦的時候都要先格式化,為什么呢?就是因為 SD 卡里面沒有建立FAT 文件系統(tǒng),所以格式化之后,建立了 FAT 文件系統(tǒng),電腦 才能識別 SD 卡上面的內(nèi)存和文件。FAT 文件系統(tǒng)根據(jù)字節(jié)長度,有FAT12、 FAT16、FAT32。
13.1 FATFS簡介 FATFS 是一個完全免費開源的 FAT 文件系統(tǒng)模塊,專門為小型的嵌入式系 統(tǒng)而設(shè)計。它完全用標(biāo)準(zhǔn) C 語言編寫,所以具有良好的硬件平臺獨立性,可以 移植到 8051、PIC、AVR、SH、Z80、H8、ARM 等系列單片機上而只需做簡 單的修改。它支持 FATl2、FATl6 和FAT32,支持多個存儲媒介;有獨立的緩 沖區(qū),可以對多個文件進行讀/寫,并特別對 8 位單片機和 16 位單片機做了優(yōu) 化。反正 FSTFS優(yōu)點蠻多,挺好用,就是了,呵呵…大家下載最新的 FSTFS 可 以在 elm-chan 這個網(wǎng)站下載到。
13.2 FATFS的移植 1. FATFS 源碼文件說明 我們這里移植示范使用的是 R0.09b 版本,在我們例程文件下有一個 R0.09b 版本的壓縮包。 我們解壓該壓縮包,會得到兩個文件夾:
其中 doc 文件夾是各種使用說明,有英文版的和日文版的。而 src 文件夾就 是我們要使用的 FATFS 源碼:
其中我們不需要修改的文件是: ff.h FATFS 和應(yīng)用模塊公用的包含文件 ff.c FATFS 模塊 diskio.h FATFS 和 disk I/O 模塊公用的包含文件 interger.h 數(shù)據(jù)類型定義 
里面還有個 option 文件夾,這個是可選的外部功能(比如支持中文等)。一 般我們使用中文的話,將 cc936.c 添加到工程里面就好了。
那么我們需要修改的文件也就兩個了。 ffconf.h FATFS 模塊配置文件 diskio.c FATFS 和 disk I/O 模塊接口層文件
2. ffconf.h 配置說明 這 ffconf.h 的頭文件里面是關(guān)于 FATFS 的各種設(shè)置,我們可以根據(jù)自己的需 要來裁剪 FATFS,已達(dá)到自己想要的標(biāo)準(zhǔn)。我們來看一下它都有那些設(shè)置: 1) _FS_TINY 這個設(shè)置是配置是使用標(biāo)準(zhǔn)模式,還是微小模式。我們使用標(biāo)準(zhǔn)模式, 這里設(shè)置為:0。 2) _FS_READONLY 是否使用只讀模式,我們選擇可讀可寫。設(shè)置為:0。 3) _FS_MINIMIZE 這個設(shè)置是選擇是否裁剪掉一些函數(shù),具體裁剪那些,大家可以查看下 面的設(shè)置說明,我們這里使用的全功能模式。設(shè)置為:0。 4) _USE_STRFUNC 這個用來設(shè)置是否支持字符串類操作,我們選擇使用。設(shè)置為:1。 5) _USE_MKFS 使用使用格式化,我們這里選擇使用。設(shè)置為:1。 6) _USE_FASTSEEK
使用使能快速定位,我們選擇使用。設(shè)置為:1。 7) _USE_LABEL 是否啟用磁盤卷標(biāo)功能。使用也可以,不使用也可以。我們這里使用。 設(shè)置為:1。 8) _USE_FORWARD 這個是在 TINY 模式下的設(shè)置,我們這里使用標(biāo)準(zhǔn)模式,不理它。 9) _CODE_PAGE 這個用于設(shè)置語言類型。我們使用的中文。設(shè)置為:936 10) _USE_LFN 該選項用于設(shè)置是否支持長文件名(還需要_CODE_PAGE 支持),取值 范圍為 0~3。0,表示不支持長文件名,1~3 是支持長文件名,但是存儲地方 不一樣。我們這里就默認(rèn)使用 FATFS 本身的存儲方式了。設(shè)置為:1。 11) _MAX_LFN 設(shè)置最大文件名長度,我們直接設(shè)置最大。設(shè)置為:255。 12) _LFN_UNICODE 是否使用 FATFS 的字符編碼。我們不使用。設(shè)置為:0 13) _FS_RPATH 這里也是一些函數(shù)裁剪,我們這里設(shè)置為:1。 14) _VOLUMES 這里設(shè)置的是支持的卷軸數(shù)量,我們掛載 SD 卡,有時候可以掛載下 FLASH,所以這里我們設(shè)置為兩個:2。 15) _MAX_SS 這里是設(shè)置扇區(qū)緩沖的最大值,我們設(shè)置為:512。 16) _MULTI_PARTITION 是否使用多重分區(qū)分配。我們這里設(shè)置為:0。 17) _USE_ERASE 使用使用扇區(qū)擦除。我們這里不那么麻煩,想使用的時候在設(shè)置。設(shè)置 為:0。 18) _WORD_ACCESS 這里定義使用權(quán)限。一般不使用。我們設(shè)置為:0。 19) _FS_REENTRANT 20) _FS_TIMEOUT 21) _SYNC_t 22) _FS_LOCK 這幾個設(shè)置,我們都沒有使用到,所以直接保持默認(rèn)狀態(tài)就好。
3. diskio.c 移植 diskio.c 是最底層的接口函數(shù)。一般需要編寫 6 個接口函數(shù),如圖:
1) disk_initialize()函數(shù)
移植代碼如下: /*-----------------------------------------------------------------------*/ /* Inidialize a Drive 初始化磁盤 */ /*-----------------------------------------------------------------------*/
DSTATUS disk_initialize ( BYTE pdrv /* Physical drive nmuber (0..) */ ) { DRESULT res = RES_ERROR; int result;
switch (pdrv) { case SD_CARD : result = SD_Init(); if(result == 0) {
} break; res = RES_OK;
case USB : break; default: break;
}
return res;
} 其實修改并不多,在這個函數(shù)里面,紅色字體部分就是 SD 卡初始化移植部 分。
2) disk_status()函數(shù)
移植代碼如下: /*-----------------------------------------------------------------------*/ /* Get Disk Status 獲取磁盤信息 */ /*-----------------------------------------------------------------------*/
DSTATUS disk_status ( BYTE pdrv /* Physical drive nmuber (0..) */ ) { pdrv = pdrv; return 0; } 這里我們不使用這個函數(shù),所以我們什么都不寫,直接返回 0 就好。
3) disk_read()函數(shù)
移植代碼如下: /*-----------------------------------------------------------------------*/ /* Read Sector(s) 讀取扇區(qū) */ /*-----------------------------------------------------------------------*/
DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address (LBA) */ BYTE count /* Number of sectors to read (1..128) */ ) { DRESULT res = RES_ERROR; int result;
switch (pdrv) { case SD_CARD : result = SD_ReadDisk(buff, sector, count); if(result) {
} else {
} res = RES_ERROR;
res = RES_OK;
break;
case USB :
break;
default: break; }
return res; } SD 卡移植是紅色字體部分。

4) disk_write()函數(shù)
移植代碼如下: /*-----------------------------------------------------------------------*/ /* Write Sector(s) */ /*-----------------------------------------------------------------------*/
#if _USE_WRITE DRESULT disk_write ( BYTE pdrv, /* Physical drive nmuber (0..) */ const BYTE *buff, /* Data to be written */ DWORD sector, /* Sector address (LBA) */ BYTE count /* Number of sectors to write (1..128) */ ) { DRESULT res = RES_ERROR; int result;
switch (pdrv) { case SD_CARD : result = SD_WriteDisk((uint8_t*)buff, sector, count); if(result == 0) { res = RES_OK; } break;
case USB : break;
default: break; } return res; } #endif

5) disk_ioctl()函數(shù)
移植代碼如下: /*-----------------------------------------------------------------------*/ /* Miscellaneous Functions 其他表參數(shù)的獲取 */ /*-----------------------------------------------------------------------*/
#if _USE_IOCTL DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE cmd, /* Control code */ void *buff /* Buffer to send/receive control data */ ) { DRESULT res = RES_PARERR;
switch (pdrv) { case SD_CARD : switch(cmd) { case CTRL_SYNC: //刷新磁盤 res = RES_OK; break; case GET_SECTOR_SIZE: //得到媒體大小 *(WORD*)buff = 512; res = RES_OK; break; case GET_BLOCK_SIZE: //塊大小 *(WORD*)buff = 8; res = RES_OK; break; case GET_SECTOR_COUNT: if(SD_ReadCapacity((uint32_t *)buff) == 0) { res = RES_OK; } break; default: break; } break;
case USB : res = RES_PARERR; break; }
return res; } #endif 紅色部分就是移植部分。
6) get_fattime()函數(shù)
這個函數(shù)沒有直接給在 diskio.c 里面,需要你自己寫。代碼如下: DWORD get_fattime(void) { return 0; } 因為我們例程里面沒有使用時間,所以,直接返回零就好。
好了,到這里我們整個移植過程也就完成了,只要我們添加到工程里面 如下:
然后編譯就可以使用了。
13.3 FATFS函數(shù)說明 FATFS 有許多函數(shù)可以提供給我們使用,主要函數(shù)如下: 1) f_mount - Register/Unregister a work area 2) f_open - Open/Create a file 3) f_close - Close a file 4) f_read - Read file 5) f_write - Write file 6) f_lseek - Move read/write pointer, Expand file size 7) f_truncate - Truncate file size 8) f_sync - Flush cached data 9) f_opendir - Open a directory 10) f_readdir - Read a directory item 11) f_getfree - Get free clusters 12) f_stat - Get file status 13) f_mkdir - Create a directory 14) f_unlink - Remove a file or directory 15) f_chmod - Change attribute 16) f_utime - Change timestamp 17) f_rename - Rename/Move a file or directory 18) f_chdir - Change current directory 19) f_chdrive - Change current drive 20) f_getcwd - Retrieve the current directory 21) f_getlabel - Get volume label 22) f_setlabel - Set volume label 23) f_forward - Forward file data to the stream directly 24) f_mkfs - Create a file system on the drive 25) f_fdisk - Divide a physical drive 26) f_gets - Read a string 27) f_putc - Write a character 28) f_puts - Write a string 29) f_printf - Write a formatted string 30) f_tell - Get the current read/write pointer 31) f_eof - Test for end-of-file on a file 32) f_size - Get size of a file 33) f_error - Test for an error on a file 在這里我們就不一一介紹這些函數(shù)的怎么使用了,大家可以查看 doc 文件下 的使用說明,在使用說明中也有一些簡單的使用例程,可以使大家很好的理解如 何使用這些函數(shù)。在這里我們就簡單講一些常用的函數(shù)。 1. f_mount()函數(shù) 這個函數(shù)用來注冊/注銷文件系統(tǒng)對象(工作區(qū)域)的函數(shù),在使用 FATFS 之 前,要先調(diào)用這個函數(shù)來注冊文件系統(tǒng),又稱掛載系統(tǒng)。 它有兩個輸入?yún)?shù): 1) 邏輯驅(qū)動器的標(biāo)號。我們在 diskio.c 中有這么一個定義:
#define SD_CARD 0 那么我們的 SD 卡的邏輯驅(qū)動器標(biāo)號就是“0”,當(dāng)我們要掛載 SD 卡的時 候,這個參數(shù)就要設(shè)置為:0。 2) 指向文件系統(tǒng)對象的指針 這個是用來存放系統(tǒng)信息的變量,它的文件類型是結(jié)構(gòu)體 FATFS,所以我們 只要定義 FATFS 類型的參數(shù),傳遞給它就可以了。而如果是注銷掉文件系統(tǒng), 那么傳遞給它一個 NULL 指針就可以了。
2. f_getfree()函數(shù) 這個函數(shù)就是我們用來讀取內(nèi)存空間要調(diào)用的函數(shù),在使用說明里面, 它也給出如何使用這個函數(shù)的例程,首先我們來看一下:
在這個例程中,我們可以看出,使用 f_getfree()來讀取容量的步驟為: 1) 掛載文件系統(tǒng)。 例程上面沒有寫出要掛載文件系統(tǒng),不過一般在進行 FATFS 的函數(shù) 操作之前都要調(diào)用 f_mount()函數(shù)掛載文件系統(tǒng)。 2) 調(diào)用 f_getfree()讀取相應(yīng)的參數(shù)。 3) 從文件系統(tǒng)參數(shù)中讀取總的內(nèi)存和空閑的內(nèi)存。
我們例程中調(diào)用的讀取內(nèi)存容量的函數(shù)如下: - /*************************************************************
- * Function Name : FATFS_GetFree
- * Description : 讀取總磁盤大小和空閑磁盤大小
- * Input : drv:磁盤編號
- * * total:保存讀取到的總磁盤大小
- * * free:保存讀取到的空閑磁盤大小
- * Output : None
- * Return : res:讀取狀態(tài)。0:成功;其他則是其他相應(yīng)的錯誤 信息。
- *************************************************************/
- uint8_t FATFS_GetFree(uint8_t *drv, uint32_t *total, uint32_t *free)
- {
- FATFS *fs1;
- u8 res;
- DWORD fre_clust=0, fre_sect=0, tot_sect=0;
- /* 得到磁盤信息及空閑簇數(shù)量 */
- res = f_getfree((const TCHAR*)drv, &fre_clust, &fs1);
- if(res == 0) //表示讀取成功
- {
- tot_sect = (fs1->n_fatent-2) * fs1->csize; //得到總扇區(qū)數(shù)
- fre_sect = fre_clust * fs1->csize; //得到空閑扇區(qū)數(shù)
- #if _MAX_SS!=512 //扇區(qū)大小不是 512 字節(jié),則轉(zhuǎn)換為 512 字節(jié)
- tot_sect *= fs1->ssize/512;
- fre_sect *= fs1->ssize/512;
- #endif
- *total = tot_sect >> 1; //單位為 KB
- *free = fre_sect >> 1; //單位為 KB
- }
-
- return res;
- }
-
- 13.4 FATFS 主函數(shù)
- int main(void)
- {
- uint8_t showData[5] = {0, 0, 0, 0, 0}, ledState; FATFS fs0, fs1;
- uint32_t free, total, i = 0;
- TFT_Init(); FLASH_Init(); GUI_DisplayInit();
- USART1_Config(9600); LED_Config(); while(SD_Init())
- {
- GUI_Show12Char(0, 126, "SD 卡初始化錯誤", RED, BLACK);
- }
- f_mount(0,&fs0); //掛載 SD 卡
- f_mount(1,&fs1); //掛載 FLASH 卡
- /* 讀取 SD 卡 FAT 的容量和空余 */
- if(FATFS_GetFree("0:", &total, &free))
- {
- }
- else
- {
- BLACK);
- BLACK);
- }
- printf(" SD 卡 FAT 錯誤!");
- GUI_Show12Char(0, 147, "SD 卡 FAT 錯誤!", RED, BLACK);
- /* 顯示 FAT 容量 */
- total >>= 10; //從 KB 轉(zhuǎn)成 MB
- free >>= 10;
- printf(" sd card total memory:%d MB\n", total);
- printf(" sd card free memory:%d MB\n", free);
- showData[0] = (total % 10000 /1000) + '0'; showData[1] = (total % 1000 /100) + '0'; showData[2] = (total % 100 /10) + '0';showData[3] = (total % 10) + '0';
- GUI_Show12Char(0, 126, "sd card total memory is: MB", RED,
- GUI_Show12Char(192, 126, showData, RED, BLACK);
- showData[0] = (total % 10000 /1000) + '0'; showData[1] = (total % 1000 /100) + '0'; showData[2] = (total % 100 /10) + '0';showData[3] = (total % 10) + '0';
- GUI_Show12Char(0, 147, "sd card free memory is: MB", RED,
- GUI_Show12Char(184, 147, showData, RED, BLACK);
- /* 讀取 FLASH 卡 FAT 的容量和空余 */
- while(FATFS_GetFree("1:", &total, &free))
- {
- f_mkfs(1, 1, 4096); //如果讀取失敗,格式化 FLASH
- i++;
- if(i > 10)
- {
- break;
- }
- }
- /* 顯示 FAT 容量 */
- if(i > 10)
- {
-
- }
- else
- {
- BLACK);
- BLACK);
- }
- printf(" FLASH FAT 錯誤!");
- GUI_Show12Char(0, 84, "FLASH FAT error!", RED, BLACK);
- printf(" FLASH total memory:%d KB\n", total);
- printf(" FLASH free memory:%d KB\n", free);
- showData[0] = (total % 10000 /1000) + '0'; showData[1] = (total % 1000 /100) + '0'; showData[2] = (total % 100 /10) + '0';showData[3] = (total % 10) + '0';
- GUI_Show12Char(0, 84, "FLASH total memory is: KB", RED,
- GUI_Show12Char(176, 84, showData, RED, BLACK);
- showData[0] = (total % 10000 /1000) + '0'; showData[1] = (total % 1000 /100) + '0'; showData[2] = (total % 100 /10) + '0';showData[3] = (total % 10) + '0';
- GUI_Show12Char(0, 105, "FLASH free memory is: KB", RED,
- GUI_Show12Char(168, 105, showData, RED, BLACK);
- while(1)
- {
- /* LED 燈閃爍 */
- i++;
- if(i>0xFFFFF)
- {
- i = 0;
- if(ledState == 0xFE)
- {
- }
- else
- {
-
- }
- ledState = 0xFF;
- ledState = 0xFE;
- LED_SetState(ledState);
- }
- }
- }
復(fù)制代碼
單片機源程序如下:
- /*******************************************************************************
- *
- * 普中科技
- --------------------------------------------------------------------------------
- * 實 驗 名 : FATFS實驗
- * 實驗說明 : 將程序下載進去后點擊復(fù)位,LCD上顯示SD卡和FLASH
- 的總?cè)萘亢涂捎脙?nèi)存,
- 如果在未插上SD卡的時候無顯示,插上SD卡后按下復(fù)位進行重新檢測
- LED指示燈閃爍。
- 按下復(fù)位開關(guān)重新運行,其他子函數(shù)注釋
- 可以參考之前的函數(shù)注釋
- * 連接方式 :
- * 注 意 : 所用函數(shù)在頭文件.c文件內(nèi)
- *******************************************************************************/
- #include "stm32f10x.h"
- #include "usart.h"
- #include "sd.h"
- #include "flash.h"
- #include "myfatapp.h"
- #include "gui.h"
- #include "led.h"
- #include "ff.h"
- void GUI_DisplayInit(void);
- /****************************************************************************
- * Function Name : main
- * Description : Main program.
- * Input : None
- * Output : None
- * Return : None
- ****************************************************************************/
- int main(void)
- {
- uint8_t showData[5] = {0, 0, 0, 0, 0}, ledState;
- FATFS fs0, fs1;
- uint32_t free, total, i = 0;
- TFT_Init();
- FLASH_Init();
- GUI_DisplayInit();
- USART1_Config(9600);
- LED_Config();
- while(SD_Init())
- {
- GUI_Show12Char(0, 126, "SD 卡初始化錯誤", RED, BLACK);
- }
-
-
- f_mount(0,&fs0); //掛載SD卡
- f_mount(1,&fs1); //掛載FLASH卡
-
- //讀取SD卡FAT的容量和空余
- if(FATFS_GetFree("0:", &total, &free))
- {
- printf(" SD卡 FAT 錯誤!");
- GUI_Show12Char(0, 147, "SD卡 FAT 錯誤!", RED, BLACK);
- }
- else
- {
- // 顯示FAT容量
- total >>= 10; //從KB轉(zhuǎn)成MB
- free >>= 10;
- printf(" sd card total memory:%d MB\n", total);
- printf(" sd card free memory:%d MB\n", free);
-
- showData[0] = (total % 10000 /1000) + '0';
- showData[1] = (total % 1000 /100) + '0';
- showData[2] = (total % 100 /10) + '0';
- showData[3] = (total % 10) + '0';
- GUI_Show12Char(0, 126, "sd card total memory is: MB", RED, BLACK);
- GUI_Show12Char(192, 126, showData, RED, BLACK);
- showData[0] = (free % 10000 /1000) + '0';
- showData[1] = (free % 1000 /100) + '0';
- showData[2] = (free % 100 /10) + '0';
- showData[3] = (free % 10) + '0';
- GUI_Show12Char(0, 167, "sd card free memory is: MB", RED, BLACK);
- GUI_Show12Char(184, 167, showData, RED, BLACK);
- }
- //讀取FLASH卡FAT的容量和空余
- while(FATFS_GetFree("1:", &total, &free))
- {
- f_mkfs(1, 1, 4096); //如果讀取失敗,格式化FLASH
- i++;
- if(i > 10)
- {
- break;
- }
- }
- //顯示FAT容量
- if(i > 10)
- {
- printf(" FLASH FAT 錯誤!");
- GUI_Show12Char(0, 84, "FLASH FAT error!", RED, BLACK);
- }
- else
- {
- printf(" FLASH total memory:%d KB\n", total);
- printf(" FLASH free memory:%d KB\n", free);
-
- showData[0] = (total % 10000 /1000) + '0';
- showData[1] = (total % 1000 /100) + '0';
- showData[2] = (total % 100 /10) + '0';
- showData[3] = (total % 10) + '0';
- GUI_Show12Char(0, 84, "FLASH total memory is: KB", RED, BLACK);
- GUI_Show12Char(176, 84, showData, RED, BLACK);
- showData[0] = (free % 10000 /1000) + '0';
- showData[1] = (free % 1000 /100) + '0';
- showData[2] = (free % 100 /10) + '0';
- showData[3] = (free % 10) + '0';
- GUI_Show12Char(0, 105, "FLASH free memory is: KB", RED, BLACK);
- GUI_Show12Char(168, 105, showData, RED, BLACK);
- }
- while(1)
- {
- /* LED燈閃爍 */
- i++;
- if(i>0xFFFFF)
- {
- i = 0;
- if(ledState == 0xFE)
- {
- ledState = 0xFF;
- }
- else
- {
- ledState = 0xFE;
- }
- LED_SetState(ledState);
- }
- }
- }
- /****************************************************************************
- * Function Name : GUI_DisplayInit
- * Description : 初始化彩屏顯示
- * Input : None
- * Output : None
- * Return : None
- ****************************************************************************/
- void GUI_DisplayInit(void)
- {
- TFT_ClearScreen(BLACK);
- GUI_Show16Chinese(80, 0, "普中科技", RED, BLACK);
- GUI_Show12Char(90, 21, "PRECHIN", RED, BLACK);
- GUI_Show12Char(60, 42, "www點prechin點com", RED, BLACK);
- GUI_Show12Char(60, 63, "FAT文件系統(tǒng)實驗", RED, BLACK);
- }
復(fù)制代碼
所有資料51hei提供下載:
實驗40:FATFS實驗.zip
(8.17 MB, 下載次數(shù): 144)
2018-9-16 16:57 上傳
點擊文件名下載附件
|