在STM32中移植FATFS文件系统

在STM32中移植FATFS文件系统
在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源代码的获取,可以到官网下载:https://www.360docs.net/doc/2a15519144.html,/fsw/ff/00index_e.html最新版本是R0.09版本,我们就移植这个版本的。

2、解压文件会得到两个文件夹,一个是doc文件夹,这里是FATFS的一些使用文档和说明,以后在文件编程的时候可以查看该文档。另一个是src文件夹,里面就是我们所要的源文件。

3、建立一个STM32的工程,为方便调试,我们应重载printf()底层函数实现串口打印输出。可以参考已经建立好的printf()打印输出工程:.viewtool./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卡文件系统相关信息

6.

复制代码

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

复制代码

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.

33. default:

34. return RES_ERROR;

35.}

36. }

复制代码

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.

33. default:return RES_ERROR;

34.}

35. }

复制代码

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

相关主题
相关文档
最新文档