新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > STM32的FATFS文件系統(tǒng)移植筆記

        STM32的FATFS文件系統(tǒng)移植筆記

        作者: 時(shí)間:2016-11-26 來(lái)源:網(wǎng)絡(luò) 收藏
        一、序言

        經(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ù):

        本文引用地址:http://www.104case.com/article/201611/321826.htm
        1. DSTATUS disk_initialize (BYTE);//SD卡的初始化
        2. DSTATUS disk_status (BYTE);//獲取SD卡的狀態(tài),這里可以不用管
        3. DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);//從SD卡讀取數(shù)據(jù)
        4. DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);//將數(shù)據(jù)寫(xiě)入SD卡,若該文件系統(tǒng)為只讀文件系統(tǒng)則不用實(shí)現(xiàn)該函數(shù)
        5. DRESULT disk_ioctl (BYTE, BYTE, void*);//獲取SD卡文件系統(tǒng)相關(guān)信息
        復(fù)制代碼



        圖1
        3、初步實(shí)現(xiàn)以上五個(gè)函數(shù)
        FATFS初始化函數(shù):

        1. DSTATUS disk_initialize (
        2. BYTE drv /* Physical drive nmuber (0..) */
        3. )
        4. {
        5. switch (drv)
        6. {
        7. case 0 :
        8. return RES_OK;
        9. case 1 :
        10. return RES_OK;
        11. case 2 :
        12. return RES_OK;
        13. case 3 :
        14. return RES_OK;
        15. default:
        16. return STA_NOINIT;
        17. }
        18. }
        復(fù)制代碼

        FATFS狀態(tài)獲取函數(shù):

        1. DSTATUS disk_status (
        2. BYTE drv /* Physical drive nmuber (0..) */
        3. )
        4. {
        5. switch (drv)
        6. {
        7. case 0 :
        8. return RES_OK;
        9. case 1 :
        10. return RES_OK;
        11. case 2 :
        12. return RES_OK;
        13. default:
        14. return STA_NOINIT;
        15. }
        16. }
        復(fù)制代碼

        FATFS底層讀數(shù)據(jù)函數(shù):

        1. DRESULT disk_read (
        2. BYTE drv, /* Physical drive nmuber (0..) */
        3. BYTE *buff, /* Data buffer to store read data */
        4. DWORD sector, /* Sector address (LBA) */
        5. BYTE count /* Number of sectors to read (1..255) */
        6. )
        7. {
        8. if( !count )
        9. {
        10. return RES_PARERR;/* count不能等于0,否則返回參數(shù)錯(cuò)誤 */
        11. }
        12. switch (drv)
        13. {
        14. case 0:
        15. if(count==1) /* 1個(gè)sector的讀操作 */
        16. {
        17. return RES_OK;
        18. }
        19. else /* 多個(gè)sector的讀操作 */
        20. {
        21. return RES_OK;
        22. }
        23. case 1:
        24. if(count==1) /* 1個(gè)sector的讀操作 */
        25. {
        26. return RES_OK;
        27. }
        28. else /* 多個(gè)sector的讀操作 */
        29. {
        30. return RES_OK;
        31. }
        32. default:
        33. return RES_ERROR;
        34. }
        35. }
        復(fù)制代碼

        FATFS底層寫(xiě)數(shù)據(jù)函數(shù):

        1. DRESULT disk_write (
        2. BYTE drv, /* Physical drive nmuber (0..) */
        3. const BYTE *buff, /* Data to be written */
        4. DWORD sector, /* Sector address (LBA) */
        5. BYTE count /* Number of sectors to write (1..255) */
        6. )
        7. {
        8. if( !count )
        9. {
        10. return RES_PARERR;/* count不能等于0,否則返回參數(shù)錯(cuò)誤 */
        11. }
        12. switch (drv)
        13. {
        14. case 0:
        15. if(count==1) /* 1個(gè)sector的寫(xiě)操作 */
        16. {
        17. return RES_OK;
        18. }
        19. else /* 多個(gè)sector的寫(xiě)操作 */
        20. {
        21. return RES_OK;
        22. }
        23. case 1:
        24. if(count==1) /* 1個(gè)sector的寫(xiě)操作 */
        25. {
        26. return RES_OK;
        27. }
        28. else /* 多個(gè)sector的寫(xiě)操作 */
        29. {
        30. return RES_OK;
        31. }
        32. default:return RES_ERROR;
        33. }
        34. }
        復(fù)制代碼

        FATFS磁盤(pán)控制函數(shù):

        1. DRESULT disk_ioctl (
        2. BYTE drv, /* Physical drive nmuber (0..) */
        3. BYTE ctrl, /* Control code */
        4. void *buff /* Buffer to send/receive control data */
        5. )
        6. {
        7. if (drv==0)
        8. {
        9. switch (ctrl)
        10. {
        11. case CTRL_SYNC :
        12. return RES_OK;
        13. case GET_SECTOR_COUNT :
        14. return RES_OK;
        15. case GET_BLOCK_SIZE :
        16. return RES_OK;
        17. case CTRL_POWER :
        18. break;
        19. case CTRL_LOCK :
        20. break;
        21. case CTRL_EJECT :
        22. break;
        23. /* MMC/SDC command */
        24. case MMC_GET_TYPE :
        25. break;
        26. case MMC_GET_CSD :
        27. break;
        28. case MMC_GET_CID :
        29. break;
        30. case MMC_GET_OCR :
        31. break;
        32. case MMC_GET_SDSTAT :
        33. break;
        34. }
        35. }else if(drv==1){
        36. switch (ctrl)
        37. {
        38. case CTRL_SYNC :
        39. return RES_OK;
        40. case GET_SECTOR_COUNT :
        41. return RES_OK;
        42. case GET_SECTOR_SIZE :
        43. return RES_OK;
        44. case GET_BLOCK_SIZE :
        45. return RES_OK;
        46. case CTRL_POWER :
        47. break;
        48. case CTRL_LOCK :
        49. break;
        50. case CTRL_EJECT :
        51. break;
        52. /* MMC/SDC command */
        53. case MMC_GET_TYPE :
        54. break;
        55. case MMC_GET_CSD :
        56. break;
        57. case MMC_GET_CID :
        58. break;
        59. case MMC_GET_OCR :
        60. break;
        61. case MMC_GET_SDSTAT :
        62. break;
        63. }
        64. }
        65. else{
        66. return RES_PARERR;
        67. }
        68. return RES_PARERR;
        69. }
        復(fù)制代碼

        以上函數(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ā)送。
        程序如下:

        1. /* Start send CMD0 till return 0x01 means in IDLE state */
        2. for(retry=0; retry<0xFFF; retry++)
        3. {
        4. r1 = MSD0_send_command(CMD0, 0, 0x95);
        5. if(r1 == 0x01)
        6. {
        7. retry = 0;
        8. break;
        9. }
        10. }
        復(fù)制代碼

        d、發(fā)送CMD8獲取卡的類(lèi)型,不同類(lèi)型的卡其初始化方式有所不同。
        e、根據(jù)卡的類(lèi)型對(duì)卡進(jìn)行初始化。具體初始化方式可以參考附件程序。
        注:在初始化SD卡之前應(yīng)該初始化SPI接口和相關(guān)的管腳。
        實(shí)現(xiàn)后的程序如下:

        1. DSTATUS disk_initialize (
        2. BYTE drv /* Physical drive nmuber (0..) */
        3. )
        4. {
        5. int Status;
        6. switch (drv)
        7. {
        8. case 0 :
        9. Status = MSD0_Init();
        10. if(Status==0){
        11. return RES_OK;
        12. }else{
        13. return STA_NOINIT;
        14. }
        15. case 1 :
        16. return RES_OK;
        17. case 2 :
        18. return RES_OK;
        19. case 3 :
        20. return RES_OK;
        21. default:
        22. return STA_NOINIT;
        23. }
        24. }
        復(fù)制代碼

        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)后的程序如下:

        1. DRESULT disk_read (
        2. BYTE drv, /* Physical drive nmuber (0..) */
        3. BYTE *buff, /* Data buffer to store read data */
        4. DWORD sector, /* Sector address (LBA) */
        5. BYTE count /* Number of sectors to read (1..255) */
        6. )
        7. {
        8. int Status;
        9. if( !count )
        10. {
        11. return RES_PARERR;/* count不能等于0,否則返回參數(shù)錯(cuò)誤 */
        12. }
        13. switch (drv)
        14. {
        15. case 0:
        16. if(count==1) /* 1個(gè)sector的讀操作 */
        17. {
        18. Status =MSD0_ReadSingleBlock( sector ,buff );
        19. if(Status == 0){
        20. return RES_OK;
        21. }else{
        22. return RES_ERROR;
        23. }
        24. }
        25. else /* 多個(gè)sector的讀操作 */
        26. {
        27. Status = MSD0_ReadMultiBlock( sector , buff ,count);
        28. if(Status == 0){
        29. return RES_OK;
        30. }else{
        31. return RES_ERROR;
        32. }
        33. }
        34. case 1:
        35. if(count==1) /* 1個(gè)sector的讀操作 */
        36. {
        37. return RES_OK;
        38. }
        39. else /* 多個(gè)sector的讀操作 */
        40. {
        41. return RES_OK;
        42. }
        43. default:
        44. return RES_ERROR;
        45. }
        46. }
        復(fù)制代碼

        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)后的程序如下:

        1. DRESULT disk_write (
        2. BYTE drv, /* Physical drive nmuber (0..) */
        3. const BYTE *buff, /* Data to be written */
        4. DWORD sector, /* Sector address (LBA) */
        5. BYTE count /* Number of sectors to write (1..255) */
        6. )
        7. {
        8. int Status;
        9. if( !count )
        10. {
        11. return RES_PARERR;/* count不能等于0,否則返回參數(shù)錯(cuò)誤 */
        12. }
        13. switch (drv)
        14. {
        15. case 0:
        16. if(count==1) /* 1個(gè)sector的寫(xiě)操作 */
        17. {
        18. Status = MSD0_WriteSingleBlock( sector , (uint8_t *)(&buff[0]) );
        19. if(Status == 0){
        20. return RES_OK;
        21. }else{
        22. return RES_ERROR;
        23. }
        24. }
        25. else /* 多個(gè)sector的寫(xiě)操作 */
        26. {
        27. Status = MSD0_WriteMultiBlock( sector , (uint8_t *)(&buff[0]) , count );
        28. if(Status == 0){
        29. return RES_OK;
        30. }else{
        31. return RES_ERROR;
        32. }
        33. }
        34. case 1:
        35. if(count==1) /* 1個(gè)sector的寫(xiě)操作 */
        36. {
        37. return RES_OK;
        38. }
        39. else /* 多個(gè)sector的寫(xiě)操作 */
        40. {
        41. return RES_OK;
        42. }
        43. default:return RES_ERROR;
        44. }
        45. }
          上一頁(yè) 1 2 下一頁(yè)

        評(píng)論


        技術(shù)專(zhuān)區(qū)

        關(guān)閉
        主站蜘蛛池模板: 班玛县| 射阳县| 连云港市| 镇江市| 宜阳县| 元江| 孟津县| 弥勒县| 灵丘县| 黄浦区| 成都市| 定边县| 祥云县| 浪卡子县| 宣威市| 红原县| 竹溪县| 贵溪市| 南靖县| 辽源市| 福泉市| 宁化县| 陈巴尔虎旗| 金湖县| 金秀| 揭西县| 朔州市| 湖北省| 达日县| 荆门市| 剑阁县| 岢岚县| 肇东市| 新宁县| 丘北县| 昌吉市| 苗栗市| 股票| 亚东县| 平利县| 芒康县|