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

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();}

     运行效果

     

     

    http://www.xdnf.cn/news/1719.html

    相关文章:

  3. Godot开发2D冒险游戏——第二节:主角光环整起来!
  4. C# new Bitmap(32043, 32043, PixelFormat.Format32bppArgb)报错:参数无效,如何将图像分块化处理?
  5. STM32F103_HAL库+寄存器学习笔记20 - CAN发送中断+ringbuffer + CAN空闲接收中断+接收所有CAN报文+ringbuffer
  6. Python爬虫去重策略:增量爬取与历史数据比对
  7. VulnHub-DC-2靶机渗透教程
  8. zip是 Python 中 `zip` 函数的一个用法
  9. 数模学习:一,层次分析法
  10. flutter 小知识
  11. 在Ubuntu 18.04 和 ROS Melodic 上编译 UFOMap
  12. 跨浏览器音频录制:实现兼容的音频捕获与WAV格式生成
  13. Spring Security认证流程
  14. LabVIEW实现Voronoi图绘制功能
  15. 【MQ篇】初识RabbitMQ保证消息可靠性
  16. 信息系统项目管理工程师备考计算类真题讲解七
  17. KMS工作原理及其安全性分析
  18. Java Agent 注入 WebSocket 篇
  19. java方法引用
  20. kotlin和MVVM的结合使用总结(二)
  21. 一种Spark程序运行指标的采集与任务诊断实现方式
  22. CE第二次作业
  23. NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve
  24. Git 的基本概念和使用方式
  25. C++跨平台开发要点
  26. Spring AI 核心概念
  27. 【Linux】网络基础和socket
  28. HGDB安全版单机修改用户密码
  29. spring-ai使用Document存储至milvus的数据结构
  30. dockercompose文件仓库
  31. [Java]动态代理
  32. CSS基础