当前位置: 首页 > news >正文

STM32移植最新版FATFS

FATFS源码下载

http://elm-chan.org/fsw/ff/00index_e.html

添加 FATFS 源码到工程

  1. 解压下载的 FATFS 源码包,将ff.cff.hffsystem.hffconf.hdiskio.h复制到工程目录下的一个新文件夹(例如FatFS)中。

  2. keil中添加源文件和路径,省略

    编译并修改错误

    完成上述操作,对整个工程代码进行编译后,出现了如下13个报错信息,通过定位报错信息可以得知,主要是由于文件系统diskio.c中对MMC、RAM、USB设备的初始化、读、写、状态获取API未定义和ff.c中对文件时间戳未定义。

    因此,接下来对文件系统的移植操作主要是针对报错信息进行处理,将diskio.c文件中的硬件设备初始化、读、写、状态获取API及ff.c文件时间戳进行适配、定义实现。

    这个错误是默认FATFS是使能RTC功能的,这里可以将其关闭

    在“ffconf.h”配置文件中将这个宏设为1即可

    实现diskio.c文件

    diskio.c文件包含了 FATFS 与底层存储设备的接口函数,需要根据实际使用的存储设备进行实现。以下是一些常见的接口函数:

    disk_status

            这个函数的功能是获取设备的状态,只有一个参数pdrv,表示物理编号。因暂时只使用了SD卡,因此除了SD卡返回正常状态,其它类型设备全部返回的是非正常状态。

    /*-----------------------------------------------------------------------*/
    /* Get Drive Status                                                      */
    /*-----------------------------------------------------------------------*/DSTATUS disk_status (BYTE pdrv                /* Physical drive nmuber to identify the drive */
    )
    {DSTATUS stat;int result;switch (pdrv) {case DEV_SD :return SD_disk_status(pdrv);}return STA_NOINIT;
    }

    disk_initialize

            disk_initialize函数是设备初始化接口,也是有一个参数pdrv,用来指定设备物理编号。因只有一个SD设备,除了SD状态中调用了SD_Init()对SD卡进行了初始化设置,其它类型全部返回了未初始化。

    /*-----------------------------------------------------------------------*/
    /* Inidialize a Drive                                                    */
    /*-----------------------------------------------------------------------*/DSTATUS disk_initialize (BYTE pdrv                                /* Physical drive nmuber to identify the drive */
    )
    {DSTATUS stat;int result;switch (pdrv) {case DEV_SD :return SD_disk_initialize(pdrv);}return STA_NOINIT;
    }
    

    disk_read

            disk_read函数有四个形参。pdrv为设备物理编号。buff是一个BYTE类型指针变量,buff指向用来存放读取到数据的存储区首地址。 sector是一个DWORD类型变量,指定要读取数据的扇区首地址。count是一个UINT类型变量,指定扇区数量。

            BYTE类型实际是unsigned char类型,DWORD类型实际是unsigned long类型, UINT类型实际是 unsigned int类型,类型定义在ff.h文件中。

    /*-----------------------------------------------------------------------*/
    /* Read Sector(s)                                                        */
    /*-----------------------------------------------------------------------*/DRESULT disk_read (BYTE pdrv,                /* Physical drive nmuber to identify the drive */BYTE *buff,                /* Data buffer to store read data */LBA_t sector,        /* Start sector in LBA */UINT count                /* Number of sectors to read */
    )
    {DRESULT res;int result;switch (pdrv) {case DEV_SD :return SD_disk_read(pdrv, buff, sector, count);         }return RES_PARERR;
    }

    disk_write

            disk_write函数有四个形参,pdrv为设备物理编号。buff指向待写入扇区数据的首地址。sector,指定要读取数据的扇区首地址。 count指定扇区数量

    /*-----------------------------------------------------------------------*/
    /* Write Sector(s)                                                       */
    /*-----------------------------------------------------------------------*/#if FF_FS_READONLY == 0DRESULT disk_write (BYTE pdrv,                        /* Physical drive nmuber to identify the drive */const BYTE *buff,        /* Data to be written */LBA_t sector,                /* Start sector in LBA */UINT count                        /* Number of sectors to write */
    )
    {DRESULT res;int result;switch (pdrv) {case DEV_SD :return SD_disk_write(pdrv, buff, sector, count);         }return RES_PARERR;
    }#endif

    disk_ioctl

            disk_ioctl函数有三个形参,pdrv为设备物理编号,cmd为控制指令,包括发出同步信号、获取扇区数目、获取扇区大小、 获取擦除块数量等等指令,buff为指令对应的数据指针。

            对于SD卡,为支持格式化功能,需要用到获取扇区数量(GET_SECTOR_COUNT)指令和获取块尺寸(GET_BLOCK_SIZE)。另外,SD卡扇区大小为512字节, 串行Flash芯片一般设置扇区大小为4096字节,所以需要用到获取扇区大小(GET_SECTOR_SIZE)指令。

    /*-----------------------------------------------------------------------*/
    /* Miscellaneous Functions                                               */
    /*-----------------------------------------------------------------------*/DRESULT disk_ioctl (BYTE pdrv,                /* Physical drive nmuber (0..) */BYTE cmd,                /* Control code */void *buff                /* Buffer to send/receive control data */
    )
    {DRESULT res;int result;switch (pdrv) {case DEV_SD :return SD_disk_ioctl(pdrv, cmd, buff);;}return RES_PARERR;
    }

    配置ffconf.h文件

    #define FF_USE_MKFS   1
    #define FF_CODE_PAGE  936
    #define FF_USE_LFN    1
    #define FF_VOLUMES    1
    #define FF_MIN_SS     512
    #define FF_MAX_SS     4096
    1. FF_USE_MKFS: 格式化功能选择,为使用FatFs格式化功能,需要把它设置为1。

    2. FF_CODE_PAGE: 语言功能选择,并要求把相关语言文件添加到工程宏。为支持简体中文文件名需要使用"936"

    3. FF_USE_LFN: 长文件名支持,默认不支持长文件名,这里配置为1,支持长文件名,并指定将文件名存储在BSS段(数据段),也就是将其作为全局变量进行存储;配置为“#define FF_USE_LFN 2”就是将 文件名存储在STACK区(栈区);配置为“#define FF_USE_LFN 3”就是将文件名存储在HEAP(堆区)。一般配置为配置为“#define FF_USE_LFN 1”。如果存储在栈空间,防止某处操作不当而溢出。

    4. FF_VOLUMES: 指定物理设备数量,这里设置为1,SD卡设备

    5. FF_MIN_SS 、FF_MAX_SS: 指定扇区大小的最小值和最大值。SD卡扇区大小一般都为512字节,W25Q64芯片扇区大小一般设置为4096字节,所以需要把_MAX_SS改为4096。

    测试代码

    变量定义

    FATFS fs;
    FATFS *pfs;
    FIL fp;
    FRESULT fres;
    DWORD fre_clust;
    uint32_t totalSpace, freeSpace;

     初始化部分

            FRESULT ret = f_mount(&fs, "0:", 0x01);log_d("f_mount result: %02X\r\n", ret);if(ret != FR_OK){log_d("f_mount failed\r\n");Error_Handler();}/* Check freeSpace space */if(f_getfree("", &fre_clust, &pfs) != FR_OK){log_d("f_getfree failed\r\n");Error_Handler();}totalSpace = (uint32_t)((pfs->n_fatent - 2) * pfs->csize * 0.5);freeSpace = (uint32_t)(fre_clust * pfs->csize * 0.5);log_d("total:%dKB, free:%dKB\r\n", totalSpace, freeSpace);/* free space is less than 1kb */if(freeSpace < 1){log_d("freeSpace not enough\r\n");Error_Handler();}/* Open file to write */log_d("f_open first.txt\r\n");if(f_open(&fp, "first.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE) != FR_OK){log_d("f_open failed\r\n");Error_Handler();}/* Writing text */f_puts("STM32 SD Card I/O Example via SPI\n", &fp);f_puts("Black Sheep Wall!!!", &fp);/* Close file */log_d("f_close first.txt\r\n");if(f_close(&fp) != FR_OK){log_d("f_close failed\r\n");Error_Handler();}/* Open file to read */log_d("f_open first.txt\r\n");if(f_open(&fp, "first.txt", FA_READ) != FR_OK){log_d("f_open failed\r\n");Error_Handler();}log_d("f_gets first.txt\r\n");while(f_gets(buffer, sizeof(buffer), &fp)){/* SWV output */log_d("%s", buffer);fflush(stdout);}log_d("\r\ndone\r\n");/* Close file */log_d("f_close first.txt\r\n");if(f_close(&fp) != FR_OK){log_d("f_close failed\r\n");Error_Handler();}/* Unmount SDCARD */log_d("f_mount unmount");if(f_mount(NULL, "0:", 1) != FR_OK) {log_d("f_mount failed (unmount)\r\n");Error_Handler();}

     运行效果

     

     

    相关文章:

  3. React在什么情况下需要用useReducer
  4. 电商Redis热点数据缓存实施规划
  5. 从节点重排看React 与 Vue3 的 Diff 算法
  6. 1、AI及LLM基础:Python语法入门教程
  7. 【Pandas】pandas DataFrame pow
  8. 实时数字人——DH_LIVE
  9. 使用Qt Quick Controls创建自定义日历组件
  10. SCADA系统:工业自动化与智能管控的核心架构
  11. 从工作到娱乐:Codigger Desktop 让桌面环境更智能
  12. Java并发编程 - ReentrantLock
  13. 运维打铁:Centos 7 安装 redis_exporter 1.3.5
  14. Vue 3 相比 Vue 2 的优势
  15. 开发 MCP Proxy(代理)也可以用 Solon AI MCP 哟!
  16. Netty线上如何做性能调优?
  17. 弄清C语言中的链表
  18. FPGA上实现YOLOv5的一般过程
  19. STM32 的 GPIO和中断
  20. 基于深度学习和单目测距的前车防撞及车道偏离预警系统
  21. git 操作
  22. STM32 串口通信
  23. 山西10岁男孩遭生母和继父殴打遇害,案件庭审延期
  24. 临汾攻坚PM2.5:一座曾经“爆表”城市的空气治理探索
  25. 叶迪奇任陆金所控股董事长,赵容奭继续担任CEO
  26. 生态环境部谈拿手持式仪器到海边测辐射:不能测量水中放射性核素含量
  27. 蔚来李斌:当下国际贸易环境有不确定性,但坚信中国汽车产业最终将占全球四成份额
  28. 举报人不服相关部门奖励“缺斤少两”,两地分别作出再认定