您的位置 首页 IC

STM32的FATFS文件体系移植笔记

一、序言经常在网上、群里看到很多人问关于STM32的FATFS文件系统移植的问题,刚好自己最近也在调试这个程序,为了让大家少走弯路,我把

一、序文

常常在网上、群里看到很多人问关于STM32的FATFS文件体系移植的问题,刚好自己最近也在调试这个程序,为了让咱们少走弯路,我把我的调试进程和办法也贡献给咱们。

二、FATFS简介
FatFs Module是一种彻底免费开源的FAT文件体系模块,专门为小型的嵌入式体系而规划。它彻底用规范C言语编写,所以具有杰出的硬件渠道独立性,能够移植到8051、PIC、AVR、SH、Z80、H8、ARM等系列单片机上而只需做简略的修正。它支撑FATl2、FATl6和FAT32,支撑多个存储前言;有独立的缓冲区,能够对多个文件进行读/写,并特别对8位单片机和16位单片机做了优化。

三、移植预备
1、FATFS源代码的获取,能够到官网下载:http://elm-chan.org/fsw/ff/00index_e.html最新版别是R0.09版别,咱们就移植这个版别的。
2、解压文件会得到两个文件夹,一个是doc文件夹,这儿是FATFS的一些运用文档和阐明,今后在文件编程的时分能够查看该文档。另一个是src文件夹,里边便是咱们所要的源文件。
3、树立一个STM32的工程,为便利调试,咱们应重载printf()底层函数完成串口打印输出。能够参阅现已树立好的printf()打印输出工程:http://www.viewtool.com/bbs/foru … d=77&extra=page%3D1
四、开端移植
1、在现已树立好的工程目录User文件夹下新建两个文件夹,FATFS_V0.09和SPI_SD_Card,FATFS_V0.09用于寄存FATFS源文件,SPI_SD_Card用于寄存SPI的驱动文件。
2、如图1将ff.c添加到工程文件夹中,并新建diskio.c文件,在diskio.c文件中完成五个函数:

  1. DSTATUS disk_initialize (BYTE);//SD卡的初始化
  2. DSTATUS disk_status (BYTE);//获取SD卡的状况,这儿能够不必管
  3. DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);//从SD卡读取数据
  4. DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);//将数据写入SD卡,若该文件体系为只读文件体系则不必完成该函数
  5. DRESULT disk_ioctl (BYTE, BYTE, void*);//获取SD卡文件体系相关信息

仿制代码

图1
3、开始完成以上五个函数
FATFS初始化函数:

  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. }

仿制代码

FATFS状况获取函数:

  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. }

仿制代码

FATFS底层读数据函数:

  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,不然回来参数过错 */
  11. }
  12. switch (drv)
  13. {
  14. case 0:
  15. if(count==1) /* 1个sector的读操作 */
  16. {
  17. return RES_OK;
  18. }
  19. else /* 多个sector的读操作 */
  20. {
  21. return RES_OK;
  22. }
  23. case 1:
  24. if(count==1) /* 1个sector的读操作 */
  25. {
  26. return RES_OK;
  27. }
  28. else /* 多个sector的读操作 */
  29. {
  30. return RES_OK;
  31. }
  32. default:
  33. return RES_ERROR;
  34. }
  35. }

仿制代码

FATFS底层写数据函数:

  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,不然回来参数过错 */
  11. }
  12. switch (drv)
  13. {
  14. case 0:
  15. if(count==1) /* 1个sector的写操作 */
  16. {
  17. return RES_OK;
  18. }
  19. else /* 多个sector的写操作 */
  20. {
  21. return RES_OK;
  22. }
  23. case 1:
  24. if(count==1) /* 1个sector的写操作 */
  25. {
  26. return RES_OK;
  27. }
  28. else /* 多个sector的写操作 */
  29. {
  30. return RES_OK;
  31. }
  32. default:return RES_ERROR;
  33. }
  34. }

仿制代码

FATFS磁盘操控函数:

  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. }

仿制代码

以上函数都只是完成一个结构,并没有做实践的工作,下一步就需要把操作SD卡的程序填充在这个结构里边。
4、完成disk_initialize()函数
该函数在挂载文件体系的时分会被调用,首要是完成读写SD卡前对SD卡进行初始化,依据SD卡的传输协议,咱们依照如下过程初始化SD卡:
a、判别SD卡是否刺进,能够经过查看SD卡卡座的CD脚电平进行判别,一般刺进卡后该引脚会变成低电平。
b、略微延时一段时间后发送至少74个时钟给SD卡。
c、发送CMD0指令给SD卡,直到SD卡回来0x01停止,这儿能够循环屡次发送。
程序如下:

  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. }

仿制代码

d、发送CMD8获取卡的类型,不同类型的卡其初始化方法有所不同。
e、依据卡的类型对卡进行初始化。详细初始化方法能够参阅附件程序。
注:在初始化SD卡之前应该初始化SPI接口和相关的管脚。
完成后的程序如下:

  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. }

仿制代码

MSD0_Init()函数在SPI_MSD0_Driver.c文件中完成。
5、完成disk_read()函数
该函数是读取SD卡扇区数据的函数,依据SD卡数据传输协议可知有读取单扇区和读取多扇区两种操作形式,为进步读文件的速度应该完成读取多扇区函数。
完成后的程序如下:

  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,不然回来参数过错 */
  12. }
  13. switch (drv)
  14. {
  15. case 0:
  16. if(count==1) /* 1个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 /* 多个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个sector的读操作 */
  36. {
  37. return RES_OK;
  38. }
  39. else /* 多个sector的读操作 */
  40. {
  41. return RES_OK;
  42. }
  43. default:
  44. return RES_ERROR;
  45. }
  46. }

仿制代码

MSD0_ReadSingleBlock()和MSD0_ReadMultiBlock()函数都是SD卡操作的底层函数,咱们在SPI_MSD0_Driver.c文件中完成。
6、完成disk_write()函数
该函数首要完成对SD卡进行写数据操作,和读数据操作相同也分单块写和多块写,主张完成多块写的方法,这样能够进步写数据速度。
完成后的程序如下:

  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,不然回来参数过错 */
  12. }
  13. switch (drv)
  14. {
  15. case 0:
  16. if(count==1) /* 1个sector的写操作 */
  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 /* 多个sector的写操作 */
  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个sector的写操作 */
  36. {
  37. return RES_OK;
  38. }
  39. else /* 多个sector的写操作 */
  40. {
  41. return RES_OK;
  42. }
  43. default:return RES_ERROR;
  44. }
  45. }
声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/258295.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部