使用STM32F103ZET6與TF卡連接,使用SPI通信方式外加FATFS文件系統,親測可用。
0.png (45.79 KB, 下載次數: 80)
下載附件
2018-9-16 17:25 上傳
0.jpg (79.98 KB, 下載次數: 72)
下載附件
2018-9-16 17:25 上傳
FAT文件系統實驗
1. 了解 FAT 文件系統 2. 學會移植 FATFS 3. 學會使用 FATFS
我們學習了 SD 卡的使用,并且學會了怎么對 SD 卡進行讀寫操作,不過要 真正應用 SD 卡,必須學習使用文件系統。什么是文件系統呢,操作系統用于明 確磁盤或分區上的文件的方法和數據結構,即在磁盤上組織文件的方法。我們電 腦的 windows 系統使用的就是 FAT 文件系統,大家都知道,一般我們新買的 SD 卡,如果沒有使用過,插入電腦的時候都要先格式化,為什么呢?就是因為 SD 卡里面沒有建立FAT 文件系統,所以格式化之后,建立了 FAT 文件系統,電腦 才能識別 SD 卡上面的內存和文件。FAT 文件系統根據字節長度,有FAT12、 FAT16、FAT32。
13.1 FATFS簡介 FATFS 是一個完全免費開源的 FAT 文件系統模塊,專門為小型的嵌入式系 統而設計。它完全用標準 C 語言編寫,所以具有良好的硬件平臺獨立性,可以 移植到 8051、PIC、AVR、SH、Z80、H8、ARM 等系列單片機上而只需做簡 單的修改。它支持 FATl2、FATl6 和FAT32,支持多個存儲媒介;有獨立的緩 沖區,可以對多個文件進行讀/寫,并特別對 8 位單片機和 16 位單片機做了優 化。反正 FSTFS優點蠻多,挺好用,就是了,呵呵…大家下載最新的 FSTFS 可 以在 elm-chan 這個網站下載到。
13.2 FATFS的移植 1. FATFS 源碼文件說明 我們這里移植示范使用的是 R0.09b 版本,在我們例程文件下有一個 R0.09b 版本的壓縮包。 我們解壓該壓縮包,會得到兩個文件夾:
其中 doc 文件夾是各種使用說明,有英文版的和日文版的。而 src 文件夾就 是我們要使用的 FATFS 源碼:
其中我們不需要修改的文件是: ff.h FATFS 和應用模塊公用的包含文件 ff.c FATFS 模塊 diskio.h FATFS 和 disk I/O 模塊公用的包含文件 interger.h 數據類型定義 
里面還有個 option 文件夾,這個是可選的外部功能(比如支持中文等)。一 般我們使用中文的話,將 cc936.c 添加到工程里面就好了。
那么我們需要修改的文件也就兩個了。 ffconf.h FATFS 模塊配置文件 diskio.c FATFS 和 disk I/O 模塊接口層文件
2. ffconf.h 配置說明 這 ffconf.h 的頭文件里面是關于 FATFS 的各種設置,我們可以根據自己的需 要來裁剪 FATFS,已達到自己想要的標準。我們來看一下它都有那些設置: 1) _FS_TINY 這個設置是配置是使用標準模式,還是微小模式。我們使用標準模式, 這里設置為:0。 2) _FS_READONLY 是否使用只讀模式,我們選擇可讀可寫。設置為:0。 3) _FS_MINIMIZE 這個設置是選擇是否裁剪掉一些函數,具體裁剪那些,大家可以查看下 面的設置說明,我們這里使用的全功能模式。設置為:0。 4) _USE_STRFUNC 這個用來設置是否支持字符串類操作,我們選擇使用。設置為:1。 5) _USE_MKFS 使用使用格式化,我們這里選擇使用。設置為:1。 6) _USE_FASTSEEK
使用使能快速定位,我們選擇使用。設置為:1。 7) _USE_LABEL 是否啟用磁盤卷標功能。使用也可以,不使用也可以。我們這里使用。 設置為:1。 8) _USE_FORWARD 這個是在 TINY 模式下的設置,我們這里使用標準模式,不理它。 9) _CODE_PAGE 這個用于設置語言類型。我們使用的中文。設置為:936 10) _USE_LFN 該選項用于設置是否支持長文件名(還需要_CODE_PAGE 支持),取值 范圍為 0~3。0,表示不支持長文件名,1~3 是支持長文件名,但是存儲地方 不一樣。我們這里就默認使用 FATFS 本身的存儲方式了。設置為:1。 11) _MAX_LFN 設置最大文件名長度,我們直接設置最大。設置為:255。 12) _LFN_UNICODE 是否使用 FATFS 的字符編碼。我們不使用。設置為:0 13) _FS_RPATH 這里也是一些函數裁剪,我們這里設置為:1。 14) _VOLUMES 這里設置的是支持的卷軸數量,我們掛載 SD 卡,有時候可以掛載下 FLASH,所以這里我們設置為兩個:2。 15) _MAX_SS 這里是設置扇區緩沖的最大值,我們設置為:512。 16) _MULTI_PARTITION 是否使用多重分區分配。我們這里設置為:0。 17) _USE_ERASE 使用使用扇區擦除。我們這里不那么麻煩,想使用的時候在設置。設置 為:0。 18) _WORD_ACCESS 這里定義使用權限。一般不使用。我們設置為:0。 19) _FS_REENTRANT 20) _FS_TIMEOUT 21) _SYNC_t 22) _FS_LOCK 這幾個設置,我們都沒有使用到,所以直接保持默認狀態就好。
3. diskio.c 移植 diskio.c 是最底層的接口函數。一般需要編寫 6 個接口函數,如圖:
1) disk_initialize()函數
移植代碼如下: /*-----------------------------------------------------------------------*/ /* 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;
} 其實修改并不多,在這個函數里面,紅色字體部分就是 SD 卡初始化移植部 分。
2) disk_status()函數
移植代碼如下: /*-----------------------------------------------------------------------*/ /* Get Disk Status 獲取磁盤信息 */ /*-----------------------------------------------------------------------*/
DSTATUS disk_status ( BYTE pdrv /* Physical drive nmuber (0..) */ ) { pdrv = pdrv; return 0; } 這里我們不使用這個函數,所以我們什么都不寫,直接返回 0 就好。
3) disk_read()函數
移植代碼如下: /*-----------------------------------------------------------------------*/ /* Read Sector(s) 讀取扇區 */ /*-----------------------------------------------------------------------*/
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()函數
移植代碼如下: /*-----------------------------------------------------------------------*/ /* 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()函數
移植代碼如下: /*-----------------------------------------------------------------------*/ /* Miscellaneous Functions 其他表參數的獲取 */ /*-----------------------------------------------------------------------*/
#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()函數
這個函數沒有直接給在 diskio.c 里面,需要你自己寫。代碼如下: DWORD get_fattime(void) { return 0; } 因為我們例程里面沒有使用時間,所以,直接返回零就好。
好了,到這里我們整個移植過程也就完成了,只要我們添加到工程里面 如下:
然后編譯就可以使用了。
13.3 FATFS函數說明 FATFS 有許多函數可以提供給我們使用,主要函數如下: 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 在這里我們就不一一介紹這些函數的怎么使用了,大家可以查看 doc 文件下 的使用說明,在使用說明中也有一些簡單的使用例程,可以使大家很好的理解如 何使用這些函數。在這里我們就簡單講一些常用的函數。 1. f_mount()函數 這個函數用來注冊/注銷文件系統對象(工作區域)的函數,在使用 FATFS 之 前,要先調用這個函數來注冊文件系統,又稱掛載系統。 它有兩個輸入參數: 1) 邏輯驅動器的標號。我們在 diskio.c 中有這么一個定義:
#define SD_CARD 0 那么我們的 SD 卡的邏輯驅動器標號就是“0”,當我們要掛載 SD 卡的時 候,這個參數就要設置為:0。 2) 指向文件系統對象的指針 這個是用來存放系統信息的變量,它的文件類型是結構體 FATFS,所以我們 只要定義 FATFS 類型的參數,傳遞給它就可以了。而如果是注銷掉文件系統, 那么傳遞給它一個 NULL 指針就可以了。
2. f_getfree()函數 這個函數就是我們用來讀取內存空間要調用的函數,在使用說明里面, 它也給出如何使用這個函數的例程,首先我們來看一下:
在這個例程中,我們可以看出,使用 f_getfree()來讀取容量的步驟為: 1) 掛載文件系統。 例程上面沒有寫出要掛載文件系統,不過一般在進行 FATFS 的函數 操作之前都要調用 f_mount()函數掛載文件系統。 2) 調用 f_getfree()讀取相應的參數。 3) 從文件系統參數中讀取總的內存和空閑的內存。
我們例程中調用的讀取內存容量的函數如下: - /*************************************************************
- * Function Name : FATFS_GetFree
- * Description : 讀取總磁盤大小和空閑磁盤大小
- * Input : drv:磁盤編號
- * * total:保存讀取到的總磁盤大小
- * * free:保存讀取到的空閑磁盤大小
- * Output : None
- * Return : res:讀取狀態。0:成功;其他則是其他相應的錯誤 信息。
- *************************************************************/
- 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;
- /* 得到磁盤信息及空閑簇數量 */
- res = f_getfree((const TCHAR*)drv, &fre_clust, &fs1);
- if(res == 0) //表示讀取成功
- {
- tot_sect = (fs1->n_fatent-2) * fs1->csize; //得到總扇區數
- fre_sect = fre_clust * fs1->csize; //得到空閑扇區數
- #if _MAX_SS!=512 //扇區大小不是 512 字節,則轉換為 512 字節
- 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 主函數
- 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 轉成 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);
- }
- }
- }
復制代碼
單片機源程序如下:
- /*******************************************************************************
- *
- * 普中科技
- --------------------------------------------------------------------------------
- * 實 驗 名 : FATFS實驗
- * 實驗說明 : 將程序下載進去后點擊復位,LCD上顯示SD卡和FLASH
- 的總容量和可用內存,
- 如果在未插上SD卡的時候無顯示,插上SD卡后按下復位進行重新檢測
- LED指示燈閃爍。
- 按下復位開關重新運行,其他子函數注釋
- 可以參考之前的函數注釋
- * 連接方式 :
- * 注 意 : 所用函數在頭文件.c文件內
- *******************************************************************************/
- #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轉成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文件系統實驗", RED, BLACK);
- }
復制代碼
所有資料51hei提供下載:
實驗40:FATFS實驗.zip
(8.17 MB, 下載次數: 144)
2018-9-16 16:57 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|