在STM32中移植FATFS文件系统
- 格式:docx
- 大小:310.40 KB
- 文档页数:19
STM32的FATFS文件系统移植笔记一、序言经常在网上、群里看到很多人问关于STM32的FATFS文件系统移植的问题,刚好Fl己最近也在调试这个程序,为了让大家少走弯路,我把我的调试过程和方法也贡献给大家。
二、FATFS 简介FatFs Module是•种完全免费开源的FAT文件系统模块,专门为小型的嵌入式系统而设计。
它完全用标准C语言编写,所以具有良好的硬件平台独立性,可以移植到8051、PIC、AVR、SH、Z80、H8、ARM等系列单片机上而只需做简单的修改。
它支持FATI2、FATI6和FAT32, 支持多个存储媒介;有独立的缓冲区,可以对多个文件进行读/写,并特别对8位单片机和16 位单片机做了优化。
三、移植准备1、F ATFS 源代码的获取,可以到官网下载:/fsw/ff/OOindex_e.html 最新版本是R0.09版本,我们就移植这个版本的。
2、解压文件会得到两个文件夹,•个是doc文件夹,这里是FATFS的-些使用文档和说明,以后在文件编程的时候可以查看该文档。
另-个是src文件夹,里面就是我们所要的源文件。
3、建立•个STM32的工程,为方便调试,我们应重载printf()底层函数实现串口打印输出。
可以参考已经建立好的printf()打印输出工程:.viewtool./bbs/foru ...d=77 &extra=page%3Dl四、开始移植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 diskjnitialize (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 diskjoctl (BYTE, BYTE, void*);//获取SD 卡文件系统相关信息6.复制代码图13、初步实现以上五个函数FATFS 初始化函数:1. DSTATUS diskjnitialize (2. BYTE drv /* Physical drive nmuber (0..) */3. )4. {5・ switch (drv)6・ {case 0 :return RES_OK;case 1 :return RES_OK;case 2 :return RES_OK;case 3 :return RES_OK;default:return STA_NOINIT;}复制代码7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.vIGNORE_JS_OP>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, 3・ BYTE *buff z 4. DWORD sector, 5. BYTE count /* Number of sectors to read (1..255) */6. )7・ {if( Icount ){return RES.PARERR; /* count 不能等于0•否则返回参数错误*/}switch (drv){case 0:if(count= = l) /* 1 个 sector 的读操作 */{return RES_OK;}else /*多个sector 的读操作*/{return RES_OK;}/* Physical drive nmuber (0..) */ /* Data buffer to store read data *//* Sector address (LBA) */8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.case 1:if(count= = l) /* 1 个 sector 的读操作 */{return RES_OK;}else /*多个sector 的读操作*/{return RES_OK;}default:return RES_ERROR;}复制代码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( Icount )9. {10. return RES^PARERR; /* count 不能等于0,否则返回参数错误*/ li. }12. switch (drv)13. {14. case 0:if(count= = l) /* 1 个 sector 的写操作 */{return RES_OK;}else /*多个sector 的写操作*/{return RES_OK;}case 1:if(count= = l) /* 1 个 sector 的写操作 */return RES_OK;27. }23. 24. 25. 26. 27. 28. 29. 30. 31. 32.33. 34. 35. 36.15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25.26.2& else /*多个sector的写操作*/29.{30.return RES_OK;31.}32.32.default: ret urn RES_ERROR;33.}34.}复制代码FATFS磁盘控制函数:1. DRESULT diskjoctl (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 CTR1__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;case MMC_GET_SDSTAT : break; } }else if(drv= = l){ 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 : b reak; 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_G 曰LSDSTAT : b reak; } } else{ return RES_PARERR; } return RES_PARERR; } 以上函数都只是实现•个框架,并没有做实际的事情,下•步就需要把操作SD 卡的程疗:填充在 这个框架里面。
4、实现 diskjnitialize()函数 该函数在挂载文件系统的时候会被调用,主要是实现读写SD 卡前对SD 卡进行初始化,32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.64.65.66.67.68.69.复制代码根据SD卡的传输协议,我们按照如下步骤初始化SD卡:a、判断SD卡是否插入,可以通过检查SD卡卡座的CD脚电平进行判断,•般插入卡后该引脚会变成低电平。
b、稍微延时段时间后发送至少74个时钟给SD卡。
c、发送CMD0命令给SD卡,直到SD卡返回0x01为」1:,这里可以循环多次发送。
程序如下:1./* Start send CMDO till return 0x01 means in IDLE state */2.for(retry=0; retry<OxFFF; retry+ + )3.{4.rl = MSDO_send_command(CMDO z0, 0x95);5.if(rl == 0x01)6・{7.8.break;9.10.复制代码d、发送CMD8获取卡的类型,不同类型的卡其初始化方式有所不同。