目录
学习目标
我们要来介绍的是FATFS文件系统,这是一个为嵌入式设计的文件系统,甚至8051系列也可以使用,好了,我们开始介绍吧!
运行结果
文件系统
负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。即在磁盘上组织文件的方法。
常用系统
- FAT/FATFS
- NTFS:基于安全性的文件系统,是Windows NT所采用的独特的文件系统结构。
- CDFS:CDFS是大部分的光盘的文件系统。
- exFAT
FATFS
FATFS文件系统FATFS是一个完全免费开源的FAT文件系统模块,专门为小型的嵌入式系统而设计。完全用标准的C语言编写,所以具有良好的硬件平台独立性。可以移植到8051、PIC、AVR、SH、Z80、H8、ARM等系列单片机上而只需做简单的修改。它支持FAT12、FAT16和FAT32,支持多个存储媒介:有独立的缓冲区,可以对多个文件进行读/写,并特别对8位单片机和16位单片机做了优化。并且FATFS是可裁剪的文件系统,所以可以适配一些内存小的MCU,只需要删掉一些功能即可。
特点
- Windows 兼容的 FAT 文件系统(支持 FAT12/FAT16/FAT32)
- 与平台无关,移植简单
- 代码量少、效率高
- 多种配置选项
- 支持多卷(物理驱动器或分区,最多 10 个卷)
- 多个 ANSI/OEM 代码页包括 DBCS
- 支持长文件名、ANSI/OEM 或 Unicode
- 支持 RTOS
- 支持多种扇区大小
- 只读、最小化的 API 和 I/O 缓冲区等
- 免费、开源
结构图
- 底层接口,包括存储媒介读或写接口(disk I/O)和供给文件创建修改时间的实时时钟,需要我们根据平台和存储介质编写移植代码。
- 中间层FATFS模块,实现了FAT文件读或写协议。FATFS模块提供的是ff.c和ff.h。除非有必要,使用者一般不用修改,使用时将头文件直接包含进去即可。
- 最顶层是应用层,使用者无需理会FATFS的内部结构和复杂的FAT协议,只需要调用FATFS模块提供给用户的一系列应用接口函数,如f_open f_read f_write和f_close等,就可以像在PC上读/写文件那样简单。
这个就是FATFS文件系统包的结构,diskio 是我们需要与硬件相关的,需要我们来修改。ff 是核心系统代码,不需要修改。然后还有 ffconf 需要我们修改相应的配置。
FATFS 模块在移植的时候,我们一般只需要修改 2 个文件,即 ffconf.h 和 diskio.c。FATFS 模块的所有配置项都是存放在 ffconf.h 里面,我们可以通过配置里面的一些选项,来满足自己的需求。接下来简单介绍几个配置选项。
- _FS_TINY。我们使用 FATFS,所以把这个选项定义为 0 即可。如果使用Tiny FATFS,就定义为1。
- _FS_READONLY。这个用来配置是不是只读,我们需要读写都用,所以这里设置为 0 即可。
- _USE_STRFUNC。这个用来设置是否支持字符串类操作,比如 f_putc,f_puts 等,比较耗内存,我们需要用到,故设置这里为 1。
- _USE_MKFS。这个用来定时是否使能格式化,我们需要用到,所以设置这里为 1。
- _USE_FASTSEEK。这个用来使能快速定位,我们设置为 1,使能快速定位。
- _USE_LABEL。这个用来设置是否支持磁盘盘符(磁盘名字)读取与设置。我们设置 为 1,使能,就可以通过相关函数读取或者设置磁盘的名字了。
- _CODE_PAGE。这个用于设置语言类型,包括很多选项,我们这里设置为 936,即简体中文(GBK 码,需要 c936.c 文件支持,该文件在 option 文件夹)。
- _USE_LFN。该选项用于设置是否支持长文件名(还需要_CODE_PAGE 支持),取值范围为 0~3。0,表示不支持长文件名,1~3 是支持长文件名,但是存储地方不一样,我们选择使用 3,通过 ff_memalloc 函数来动态分配长文件名的存储区域。
- _VOLUMES。用于设置 FATFS 支持的逻辑设备数目,我们设置为 2,即支持 2 个设备。
- _MAX_SS。扇区缓冲的最大值,一般设置为 512。
移植步骤
- 数据类型:在 integer.h 里面去定义好数据的类型。这里需要了解你用的编译器的数 据类型,并根据编译器定义好数据类型。
- 配置:通过 ffconf.h 配置 FATFS 的相关功能,以满足你的需要。
- 函数编写:打开 diskio.c,进行底层驱动编写,一般需要编写 6 个接口函数。
第一步,我们使用的是 MDK5.11a 编译器,器数据类型和 integer.h 里面定义的一致,所以此步,我们不需要做任何改动。
第二步,关于 ffconf.h 里面的相关配置,我们在前面已经有介绍(之前介绍的 10 个配置),我们将对应配置修改为我们介绍时候的值即可,其他的配置用默认配置。
第三步,因为 FATFS 模块完全与磁盘 I/O 层分开,因此需要下面的函数来实现底层物理磁盘的读写与获取当前时间。底层磁盘 I/O 模块并不是 FATFS 的一部分,并且必须由用户提供。这些函数一般有 6 个,在 diskio.c 里面。
disk_initialize
主要用来初始化磁盘。
disk_status
返回磁盘状态。
disk_read
首先选择磁盘,然后需要读的数据大小,所以需要做好适配。
disk_write
同上。
disk_ioctl
除了读写之外的其他参数。
get_fattime
获取时间。
代码
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "key.h"
#include "sram.h"
#include "malloc.h"
#include "usmart.h"
#include "sdio_sdcard.h"
#include "malloc.h"
#include "w25qxx.h"
#include "ff.h"
#include "exfuns.h"
int main(void)
{
FIL fp;
FRESULT result;
UINT bww;
char buf[100];
u32 total,free;
u8 t=0;
u8 res=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口波特率为115200
LED_Init(); //初始化LED
usmart_dev.init(84); //初始化USMART
LCD_Init(); //LCD初始化
KEY_Init(); //按键初始化
W25QXX_Init(); //初始化W25Q128
my_mem_init(SRAMIN); //初始化内部内存池
my_mem_init(SRAMCCM); //初始化CCM内存池
POINT_COLOR=RED;//设置字体为红色
LCD_ShowString(30,90,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,110,200,16,16,"FATFS TEST");
LCD_ShowString(30,130,200,16,16,"Use USMART for test");
while(SD_Init())//检测不到SD卡
{
LCD_ShowString(30,150,200,16,16,"SD Card Error!");
delay_ms(500);
LCD_ShowString(30,150,200,16,16,"Please Check! ");
delay_ms(500);
LED0=!LED0;//DS0闪烁
}
exfuns_init(); //为fatfs相关变量申请内存
f_mount(fs[0],"0:",1); //挂载SD卡
res=f_mount(fs[1],"1:",1); //挂载FLASH.
if(res==0X0D)//FLASH磁盘,FAT文件系统错误,重新格式化FLASH
{
LCD_ShowString(30,150,200,16,16,"Flash Disk Formatting..."); //格式化FLASH
res=f_mkfs("1:",1,4096);//格式化FLASH,1,盘符;1,不需要引导区,8个扇区为1个簇
if(res==0)
{
f_setlabel((const TCHAR *)"1:ALIENTEK"); //设置Flash磁盘的名字为:ALIENTEK
LCD_ShowString(30,150,200,16,16,"Flash Disk Format Finish"); //格式化完成
}else LCD_ShowString(30,150,200,16,16,"Flash Disk Format Error "); //格式化失败
delay_ms(1000);
}
LCD_Fill(30,150,240,150+16,WHITE); //清除显示
while(exf_getfree("0",&total,&free)) //得到SD卡的总容量和剩余容量
{
LCD_ShowString(30,150,200,16,16,"SD Card Fatfs Error!");
delay_ms(200);
LCD_Fill(30,150,240,150+16,WHITE); //清除显示
delay_ms(200);
LED0=!LED0;//DS0闪烁
}
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(30,150,200,16,16,"FATFS OK!");
LCD_ShowString(30,170,200,16,16,"SD Total Size: MB");
LCD_ShowString(30,190,200,16,16,"SD Free Size: MB");
LCD_ShowNum(30+8*14,170,total>>10,5,16); //显示SD卡总容量 MB
LCD_ShowNum(30+8*14,190,free>>10,5,16); //显示SD卡剩余容量 MB
result = f_open (& fp, "0:1.txt", FA_CREATE_ALWAYS | FA_WRITE);
f_write (&fp," test" , 50, & bww);
f_close(&fp);
result = f_open (& fp, "0:1.txt", FA_READ);
f_read (& fp, buf,100, & bww);
f_close(&fp);
LCD_ShowString(30,210,230,16,16,(u8 *)buf);
while(1)
{
t++;
delay_ms(200);
LED0=!LED0;
}
}
总结
文件系统,目前感觉用不太到,而且都是偏向工程类的,其实不能像例程写的这么简单,但用来了解一下还是可以的。