STM32的FATFS文件系統(tǒng)移植筆記
經(jīng)常在網(wǎng)上、群里看到很多人問(wèn)關(guān)于STM32的FATFS文件系統(tǒng)移植的問(wèn)題,剛好自己最近也在調(diào)試這個(gè)程序,為了讓大家少走彎路,我把我的調(diào)試過(guò)程和方法也貢獻(xiàn)給大家。
二、FATFS簡(jiǎn)介
FatFs Module是一種完全免費(fèi)開(kāi)源的FAT文件系統(tǒng)模塊,專(zhuān)門(mén)為小型的嵌入式系統(tǒng)而設(shè)計(jì)。它完全用標(biāo)準(zhǔn)C語(yǔ)言編寫(xiě),所以具有良好的硬件平臺(tái)獨(dú)立性,可以移植到8051、PIC、AVR、SH、Z80、H8、ARM等系列單片機(jī)上而只需做簡(jiǎn)單的修改。它支持FATl2、FATl6和FAT32,支持多個(gè)存儲(chǔ)媒介;有獨(dú)立的緩沖區(qū),可以對(duì)多個(gè)文件進(jìn)行讀/寫(xiě),并特別對(duì)8位單片機(jī)和16位單片機(jī)做了優(yōu)化。
三、移植準(zhǔn)備
1、FATFS源代碼的獲取,可以到官網(wǎng)下載:http://elm-chan.org/fsw/ff/00index_e.html最新版本是R0.09版本,我們就移植這個(gè)版本的。
2、解壓文件會(huì)得到兩個(gè)文件夾,一個(gè)是doc文件夾,這里是FATFS的一些使用文檔和說(shuō)明,以后在文件編程的時(shí)候可以查看該文檔。另一個(gè)是src文件夾,里面就是我們所要的源文件。
3、建立一個(gè)STM32的工程,為方便調(diào)試,我們應(yīng)重載printf()底層函數(shù)實(shí)現(xiàn)串口打印輸出。可以參考已經(jīng)建立好的printf()打印輸出工程:http://www.viewtool.com/bbs/foru ... d=77&extra=page%3D1
四、開(kāi)始移植
1、在已經(jīng)建立好的工程目錄User文件夾下新建兩個(gè)文件夾,F(xiàn)ATFS_V0.09和SPI_SD_Card,F(xiàn)ATFS_V0.09用于存放FATFS源文件,SPI_SD_Card用于存放SPI的驅(qū)動(dòng)文件。
2、如圖1將ff.c添加到工程文件夾中,并新建diskio.c文件,在diskio.c文件中實(shí)現(xiàn)五個(gè)函數(shù):
- DSTATUS disk_initialize (BYTE);//SD卡的初始化
- DSTATUS disk_status (BYTE);//獲取SD卡的狀態(tài),這里可以不用管
- DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);//從SD卡讀取數(shù)據(jù)
- DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);//將數(shù)據(jù)寫(xiě)入SD卡,若該文件系統(tǒng)為只讀文件系統(tǒng)則不用實(shí)現(xiàn)該函數(shù)
- DRESULT disk_ioctl (BYTE, BYTE, void*);//獲取SD卡文件系統(tǒng)相關(guān)信息
圖1
3、初步實(shí)現(xiàn)以上五個(gè)函數(shù)
FATFS初始化函數(shù):
- DSTATUS disk_initialize (
- BYTE drv /* Physical drive nmuber (0..) */
- )
- {
- switch (drv)
- {
- case 0 :
- return RES_OK;
- case 1 :
- return RES_OK;
- case 2 :
- return RES_OK;
- case 3 :
- return RES_OK;
- default:
- return STA_NOINIT;
- }
- }
FATFS狀態(tài)獲取函數(shù):
- DSTATUS disk_status (
- BYTE drv /* Physical drive nmuber (0..) */
- )
- {
- switch (drv)
- {
- case 0 :
- return RES_OK;
- case 1 :
- return RES_OK;
- case 2 :
- return RES_OK;
- default:
- return STA_NOINIT;
- }
- }
FATFS底層讀數(shù)據(jù)函數(shù):
- DRESULT disk_read (
- BYTE drv, /* 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..255) */
- )
- {
- if( !count )
- {
- return RES_PARERR;/* count不能等于0,否則返回參數(shù)錯(cuò)誤 */
- }
- switch (drv)
- {
- case 0:
- if(count==1) /* 1個(gè)sector的讀操作 */
- {
- return RES_OK;
- }
- else /* 多個(gè)sector的讀操作 */
- {
- return RES_OK;
- }
- case 1:
- if(count==1) /* 1個(gè)sector的讀操作 */
- {
- return RES_OK;
- }
- else /* 多個(gè)sector的讀操作 */
- {
- return RES_OK;
- }
- default:
- return RES_ERROR;
- }
- }
FATFS底層寫(xiě)數(shù)據(jù)函數(shù):
- DRESULT disk_write (
- BYTE drv, /* Physical drive nmuber (0..) */
- const BYTE *buff, /* Data to be written */
- DWORD sector, /* Sector address (LBA) */
- BYTE count /* Number of sectors to write (1..255) */
- )
- {
- if( !count )
- {
- return RES_PARERR;/* count不能等于0,否則返回參數(shù)錯(cuò)誤 */
- }
- switch (drv)
- {
- case 0:
- if(count==1) /* 1個(gè)sector的寫(xiě)操作 */
- {
- return RES_OK;
- }
- else /* 多個(gè)sector的寫(xiě)操作 */
- {
- return RES_OK;
- }
- case 1:
- if(count==1) /* 1個(gè)sector的寫(xiě)操作 */
- {
- return RES_OK;
- }
- else /* 多個(gè)sector的寫(xiě)操作 */
- {
- return RES_OK;
- }
- default:return RES_ERROR;
- }
- }
FATFS磁盤(pán)控制函數(shù):
- DRESULT disk_ioctl (
- BYTE drv, /* Physical drive nmuber (0..) */
- BYTE ctrl, /* Control code */
- void *buff /* Buffer to send/receive control data */
- )
- {
- if (drv==0)
- {
- switch (ctrl)
- {
- case CTRL_SYNC :
- return RES_OK;
- case GET_SECTOR_COUNT :
- return RES_OK;
- case GET_BLOCK_SIZE :
- return RES_OK;
- case CTRL_POWER :
- break;
- case CTRL_LOCK :
- break;
- case CTRL_EJECT :
- break;
- /* MMC/SDC command */
- case MMC_GET_TYPE :
- break;
- case MMC_GET_CSD :
- break;
- case MMC_GET_CID :
- break;
- case MMC_GET_OCR :
- break;
- case MMC_GET_SDSTAT :
- break;
- }
- }else if(drv==1){
- switch (ctrl)
- {
- case CTRL_SYNC :
- return RES_OK;
- case GET_SECTOR_COUNT :
- return RES_OK;
- case GET_SECTOR_SIZE :
- return RES_OK;
- case GET_BLOCK_SIZE :
- return RES_OK;
- case CTRL_POWER :
- break;
- case CTRL_LOCK :
- break;
- case CTRL_EJECT :
- break;
- /* MMC/SDC command */
- case MMC_GET_TYPE :
- break;
- case MMC_GET_CSD :
- break;
- case MMC_GET_CID :
- break;
- case MMC_GET_OCR :
- break;
- case MMC_GET_SDSTAT :
- break;
- }
- }
- else{
- return RES_PARERR;
- }
- return RES_PARERR;
- }
以上函數(shù)都只是實(shí)現(xiàn)一個(gè)框架,并沒(méi)有做實(shí)際的事情,下一步就需要把操作SD卡的程序填充在這個(gè)框架里面。
4、實(shí)現(xiàn)disk_initialize()函數(shù)
該函數(shù)在掛載文件系統(tǒng)的時(shí)候會(huì)被調(diào)用,主要是實(shí)現(xiàn)讀寫(xiě)SD卡前對(duì)SD卡進(jìn)行初始化,根據(jù)SD卡的傳輸協(xié)議,我們按照如下步驟初始化SD卡:
a、判斷SD卡是否插入,可以通過(guò)檢查SD卡卡座的CD腳電平進(jìn)行判斷,一般插入卡后該引腳會(huì)變成低電平。
b、稍微延時(shí)一段時(shí)間后發(fā)送至少74個(gè)時(shí)鐘給SD卡。
c、發(fā)送CMD0命令給SD卡,直到SD卡返回0x01為止,這里可以循環(huán)多次發(fā)送。
程序如下:
- /* Start send CMD0 till return 0x01 means in IDLE state */
- for(retry=0; retry<0xFFF; retry++)
- {
- r1 = MSD0_send_command(CMD0, 0, 0x95);
- if(r1 == 0x01)
- {
- retry = 0;
- break;
- }
- }
d、發(fā)送CMD8獲取卡的類(lèi)型,不同類(lèi)型的卡其初始化方式有所不同。
e、根據(jù)卡的類(lèi)型對(duì)卡進(jìn)行初始化。具體初始化方式可以參考附件程序。
注:在初始化SD卡之前應(yīng)該初始化SPI接口和相關(guān)的管腳。
實(shí)現(xiàn)后的程序如下:
- DSTATUS disk_initialize (
- BYTE drv /* Physical drive nmuber (0..) */
- )
- {
- int Status;
- switch (drv)
- {
- case 0 :
- Status = MSD0_Init();
- if(Status==0){
- return RES_OK;
- }else{
- return STA_NOINIT;
- }
- case 1 :
- return RES_OK;
- case 2 :
- return RES_OK;
- case 3 :
- return RES_OK;
- default:
- return STA_NOINIT;
- }
- }
MSD0_Init()函數(shù)在SPI_MSD0_Driver.c文件中實(shí)現(xiàn)。
5、實(shí)現(xiàn)disk_read()函數(shù)
該函數(shù)是讀取SD卡扇區(qū)數(shù)據(jù)的函數(shù),根據(jù)SD卡數(shù)據(jù)傳輸協(xié)議可知有讀取單扇區(qū)和讀取多扇區(qū)兩種操作模式,為提高讀文件的速度應(yīng)該實(shí)現(xiàn)讀取多扇區(qū)函數(shù)。
實(shí)現(xiàn)后的程序如下:
- DRESULT disk_read (
- BYTE drv, /* 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..255) */
- )
- {
- int Status;
- if( !count )
- {
- return RES_PARERR;/* count不能等于0,否則返回參數(shù)錯(cuò)誤 */
- }
- switch (drv)
- {
- case 0:
- if(count==1) /* 1個(gè)sector的讀操作 */
- {
- Status =MSD0_ReadSingleBlock( sector ,buff );
- if(Status == 0){
- return RES_OK;
- }else{
- return RES_ERROR;
- }
- }
- else /* 多個(gè)sector的讀操作 */
- {
- Status = MSD0_ReadMultiBlock( sector , buff ,count);
- if(Status == 0){
- return RES_OK;
- }else{
- return RES_ERROR;
- }
- }
- case 1:
- if(count==1) /* 1個(gè)sector的讀操作 */
- {
- return RES_OK;
- }
- else /* 多個(gè)sector的讀操作 */
- {
- return RES_OK;
- }
- default:
- return RES_ERROR;
- }
- }
MSD0_ReadSingleBlock()和MSD0_ReadMultiBlock()函數(shù)都是SD卡操作的底層函數(shù),我們?cè)赟PI_MSD0_Driver.c文件中實(shí)現(xiàn)。
6、實(shí)現(xiàn)disk_write()函數(shù)
該函數(shù)主要實(shí)現(xiàn)對(duì)SD卡進(jìn)行寫(xiě)數(shù)據(jù)操作,和讀數(shù)據(jù)操作一樣也分單塊寫(xiě)和多塊寫(xiě),建議實(shí)現(xiàn)多塊寫(xiě)的方式,這樣可以提高寫(xiě)數(shù)據(jù)速度。
實(shí)現(xiàn)后的程序如下:
- DRESULT disk_write (
- BYTE drv, /* Physical drive nmuber (0..) */
- const BYTE *buff, /* Data to be written */
- DWORD sector, /* Sector address (LBA) */
- BYTE count /* Number of sectors to write (1..255) */
- )
- {
- int Status;
- if( !count )
- {
- return RES_PARERR;/* count不能等于0,否則返回參數(shù)錯(cuò)誤 */
- }
- switch (drv)
- {
- case 0:
- if(count==1) /* 1個(gè)sector的寫(xiě)操作 */
- {
- Status = MSD0_WriteSingleBlock( sector , (uint8_t *)(&buff[0]) );
- if(Status == 0){
- return RES_OK;
- }else{
- return RES_ERROR;
- }
- }
- else /* 多個(gè)sector的寫(xiě)操作 */
- {
- Status = MSD0_WriteMultiBlock( sector , (uint8_t *)(&buff[0]) , count );
- if(Status == 0){
- return RES_OK;
- }else{
- return RES_ERROR;
- }
- }
- case 1:
- if(count==1) /* 1個(gè)sector的寫(xiě)操作 */
- {
- return RES_OK;
- }
- else /* 多個(gè)sector的寫(xiě)操作 */
- {
- return RES_OK;
- }
- default:return RES_ERROR;
- }
- }
相關(guān)推薦
技術(shù)專(zhuān)區(qū)
- FPGA
- DSP
- MCU
- 示波器
- 步進(jìn)電機(jī)
- Zigbee
- LabVIEW
- Arduino
- RFID
- NFC
- STM32
- Protel
- GPS
- MSP430
- Multisim
- 濾波器
- CAN總線
- 開(kāi)關(guān)電源
- 單片機(jī)
- PCB
- USB
- ARM
- CPLD
- 連接器
- MEMS
- CMOS
- MIPS
- EMC
- EDA
- ROM
- 陀螺儀
- VHDL
- 比較器
- Verilog
- 穩(wěn)壓電源
- RAM
- AVR
- 傳感器
- 可控硅
- IGBT
- 嵌入式開(kāi)發(fā)
- 逆變器
- Quartus
- RS-232
- Cyclone
- 電位器
- 電機(jī)控制
- 藍(lán)牙
- PLC
- PWM
- 汽車(chē)電子
- 轉(zhuǎn)換器
- 電源管理
- 信號(hào)放大器
評(píng)論