FatFs 学习笔记

本文摘自《STM32 HAL 库开发实战指南 —基于野火 F407 霸天虎开发板》

FatFs源文件说明

  • option 文件夹下是一些可选的外部 c 文件,包含了多语言支持需要用到的文件和转换
    函数。
  • diskio.c 文件是 FatFs 移植最关键的文件,它为文件系统提供了最底层的访问 SPI Flash
    芯片的方法,FatFs 有且仅有它需要用到与 SPI Flash 芯片相关的函数。diskio.h 定义了
    FatFs 用到的宏,以及 diskio.c 文件内与底层硬件接口相关的函数声明。
  • 00history.txt 介绍了 FatFs 的版本更新情况。
  • 00readme.txt 说明了当前目录下 diskio.c 、diskio.h、ff.c、ff.h、integer.h 的功能。
  • integer.h:文件中包含了一些数值类型定义。
  • diskio.c:包含底层存储介质的操作函数,这些函数需要用户自己实现,主要添加
    底层驱动函数。
  • ff.c: FatFs 核心文件,文件管理的实现方法。该文件独立于底层介质操作文件的
    函数,利用这些函数实现文件的读写。
  • cc936.c:本文件在 option 目录下,是简体中文支持所需要添加的文件,包含了简
    体中文的 GBK 和 Unicode 相互转换功能函数。
  • ffconf.h:这个头文件包含了对 FatFs 功能配置的宏定义,通过修改这些宏定义就可
    以裁剪 FatFs 的功能。如需要支持简体中文,需要把 ffconf.h 中的_CODE_PAGE
    的宏改成 936 并把上面的 cc936.c 文件加入到工程之中。

移植过程讲解

FatFs 组件是 FatFs 的主体,文件都在源码 src 文件夹中,其中 ff.c、ff.h、integer.h 以及
diskio.h 四个文件我们不需要改动,只需要修改 ffconf.h 和 diskio.c 两个文件。

ffconf.h 主要是配置FatFs 要支持什么功能
diskio.c 是FatFs 与底层的接口,需要自己实现

1、支持简体中文

为支持简体中文长文件名称需要添加 ff_convert 和 ff_wtoupper 函数,实际这两个
已经在 cc936.c 文件中实现了,我们只要直接把 cc936.c 文件添加到工程中就可以了。

2、必须移植的功能函数
  • 设备状态获取
    DSTATUS disk_status (BYTE pdrv) //,pdrv是设备的物理编号,状态异常返回STA_NOINIT
  • 设备初始化
    DSTATUS disk_initialize(BYTE pdrv)
  • 扇区读取
    DRESULT disk_read (
    BYTE pdrv, /* 设备物理编号(0…) */
    BYTE buff, / 数据缓存区 /
    DWORD sector, /
    扇区首地址 /
    UINT count /
    扇区个数(1…128) */
    )
    BYTE 类型实际是 unsigned char 类型,DWORD 类型实际是 unsigned long 类型,UINT
    类型实际是 unsigned int 类型,类型定义在 integer.h 文件中。
3、创建文件,写入文件的功能函数

当 ffconf.h 内宏定义_FS_READONLY == 0时,需要支持以下函数

  • 扇区写入
    DRESULT disk_write (
    BYTE pdrv, /* 设备物理编号(0…) */
    const BYTE buff, / 欲写入数据的缓存区 /
    DWORD sector, /
    扇区首地址 /
    UINT count /
    扇区个数(1…128) */
    )
  • 其他控制
    DRESULT disk_ioctl (
    BYTE pdrv, /* 物理编号 /
    BYTE cmd, /
    控制指令 */
    void buff / 写入或者读取数据地址指针 */
    )
    cmd 为控制指令,包括发出同步信号、获取扇区数目、获取扇区大小、获取擦除块数量等等指令,buff 为指令对应的数据指针
  • 时间戳获取
    __weak DWORD get_fattime(void)
    get_fattime 函数用于获取当前时间戳,在 ff.c 文件中被调用。FatFs 在文件创建、被修
    改时会记录时间,这里我们直接使用赋值方法设定时间戳。为更好的记录时间,可以使用
    控制器 RTC 功能,
4、FatFs 功能配置

其他函数的移植,用到很少,就以上6个函数移植完,就可以实现大部分常用功能了。

  • #define _USE_MKFS 1
    格式化功能选择,为使用 FatFs 格式化功能,需要把它设置为 1
  • #define _CODE_PAGE 936
    语言功能选择,并要求把相关语言文件添加到工程宏。
  • #define _USE_LFN 2
    长文件名支持,默认不支持长文件名,这里配置为 2,支持长文件名,并指定使用栈空间为缓冲区。
  • #define _VOLUMES 2
    指定物理设备数量,这里设置为 2,包括预留 SD 卡和 SPI Flash 芯片。
  • #define _MIN_SS 512
  • #define _MAX_SS 4096
    指定扇区大小的最小值和最大值。SD 卡扇区大小一般都为 512 字节,SPI Flash 芯片扇区大小一般设置为 4096 字节,所以需要把_MAX_SS改为 4096。

FatFs 功能使用

1、FatFs常用变量说明
  • FATFS fs FatFs 文件系统对象
    FATFS 是在 ff.h 文件定义的一个结构体类型,针对的对象是物理设备,包含了物理设备的物理编号、扇区大小等等信息,一般我们都需要为每个物理设备定义一个 FATFS 变量。
  • FIL fnew 文件对象
    FIL 也是在 ff.h 文件定义的一个结构体类型,针对的对象是文件系统内具体的文件,包含了文件很多基本属性,比如文件大小、路径、当前读写地址等等。如果需要在同一时间打开多个文件进行读写,才需要定义多个 FIL 变量,不然一般定义一个 FIL 变量即可。
  • FRESULT res_flash 文件操作结果
    FRESULT 是也在 ff.h 文件定义的一个枚举类型,作为 FatFs 函数的返回值类型,主要管理 FatFs 运行中出现的错误。总共有 19 种错误类型,包括物理设备读写错误、找不到文件、没有挂载工作空间等等错误。这在实际编程中非常重要,当有错误出现是我们要停止文件读写,通过返回值我们可以快速定位到错误发生的可能地点。如果运行没有错误才返回 FR_OK。
  • UINT fnum 文件成功读写数量
    fnum 是个 32 位无符号整形变量,用来记录实际读取或者写入数据的数组
2、文件系统初始化
  • Flash 挂载文件系统,文件系统挂载时会对 SPI 设备初化
res_flash = f_mount(&fs,"1:",1);
if (res_flash == FR_NO_FILESYSTEM) {
printf("》FLASH 还没有文件系统,即将进行格式化.. .\r\n");
}
else if (res_flash!=FR_OK) {
printf("!!外部 Flash 挂载文件系统失败。(%d)\r\n",res_flash);
printf("!!可能原因:SPI Flash 初始化不成功。\r\n");
while (1);
} 
else {
printf("》文件系统挂载成功,可以进行读写测试\r\n");
}

  • 创建(格式化)文件系统
res_flash=f_mkfs("1:",0,0);
if (res_flash == FR_OK) {
printf("》FLASH 已成功格式化文件系统。\r\n");
/* 格式化后,先取消挂载 */
res_flash = f_mount(NULL,"1:",1);
/* 重新挂载 */
res_flash = f_mount(&fs,"1:",1);
} else {
LED_RED;
printf("《《格式化失败。》》\r\n");
while (1);
}
  • 写入数据
/* 打开文件,如果文件不存在则创建它 */
res_flash = f_open(&fnew, "1:FatFs 读写测试文件.txt",FA_CREATE_ALWAYS | FA_WRITE );
if ( res_flash == FR_OK ) 
{
	printf("》打开/创建 FatFs 读写测试文件.txt 文件成功,向文件写入数据。\r\n");
	/* 将指定存储区内容写入到文件内 */
	res_flash=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum);
	if (res_flash==FR_OK) 
	{
		printf("》文件写入成功,写入字节数据:%d\n",fnum);
		printf("》向文件写入的数据为:\r\n%s\r\n",WriteBuffer);
	} 
	else 
	{
		printf("!!文件写入失败:(%d)\n",res_flash);
	}
	/* 不再读写,关闭文件 */
	f_close(&fnew);
}
else 
{
	printf("!!打开/创建文件失败。\r\n");
}
  • 读取数据
res_flash = f_open(&fnew, "1:FatFs 读写测试文件.txt", FA_OPEN_EXISTING | FA_READ);
if (res_flash == FR_OK) {
	printf("》打开文件成功。\r\n");
	res_flash = f_read(&fnew, ReadBuffer, sizeof(ReadBuffer), &fnum);
	if (res_flash==FR_OK) 
	{
		printf("》文件读取成功,读到字节数据:%d\r\n",fnum);
		printf("》读取得的文件数据为:\r\n%s \r\n", ReadBuffer);
	} 
	else 
	{
		printf("!!文件读取失败:(%d)\n",res_flash);
	}
} 
else 
{
	printf("!!打开文件失败。\r\n");
}
/* 不再读写,关闭文件 */
f_close(&fnew);

}
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值