标题: 嵌入式FAT16/32文件系统 全面了解 [打印本页]
作者: 51hei小林 时间: 2016-10-21 13:04
标题: 嵌入式FAT16/32文件系统 全面了解
1. 总则
本文件系统完全兼容FAT16/FAT32文件系统总共两种格式,兼容长文件名,兼容文字编码GB2312/UNICODE汉字编码(文件名完全支持中文),实现了支持子目录,实现了支持文件的读取,写入,删除,创建等文件系统常用功能。总之,本文件系统代码全部使用C代码编写,可以移植去各种单片机平台上面实现文件系统模块。
2. 文件系统支持路径字符串的原则
1) 盘符原则
a) 盘符原则,盘符命名由C开始,到Z结束
2) 文件名原则(长文件名的长度不超过250字符的字节)
a) 文件名可是文件名与扩展名混合组成, 1)短文件名不要超过8个字节,长文件名不要超过250字节 2)扩展名一般不要超过3个字节
b) 文件名首字符不要为数字
c) 文件名的字符串大小写不作区分
3. 文件系统功能论据
1) 该文件系统完全兼容FAT16/FAT32文件系统总共两种格式,兼容长文件名,兼容文字编码GB2312/UNICODE汉字编码(文件名完全支持中文),实现了支持子目录,实现了支持文件的读取,写入,删除,创建等文件系统常用功能。
2) 本文件系统代码全部使用C代码编写,代码可以移植去各种单片机平台上面实现文件系统模块运行。在单片机上运行程序员要把磁盘虚拟驱动替换为SD卡或者磁盘驱动。
3) 本文件系统代码实现了文件读写缓冲:文件内存缓冲越大,文件读写越快,其大小可以用编译宏EnableFileBuf,TotalFileBUFsQTYeachFCB,FileBUFSize来设置(在配置文件fat_cfg.h中)。
4. 文件系统源代码文件说明举例
1) fat.c—文件系统代码
2) fat.h—文件系统函数声明文件
3) Fat_cfg.h—配置文件文件系统
4) Types.h—文件系统数据类型重替换的文件
5) Flash_management.c—磁盘虚拟驱动
6) Time.c—RTC实时时钟的驱动文件,文件存储,修改,创建时间提供
5. 文件系统重要占用内存数据结构(仅供参考,实际情况请参考配置文件fat_cfg.h)
1) 分区数据结构—支持FAT16/FAT32
structpartition_BPB{
charpartition_id; //从C开始到Z结束
char system_id;//分区类型 0C-FAT32,06-FAT16 ect..
long relative_sector;//分区起始扇区号
longtotal_sector; //分区总扇区数
intbytes_per_sector;//每扇区字节数
charsector_per_cluster; //每簇扇区数
int reservedsector; //保留扇区数
charnumbers_of_FAT;//FAT副本数
intboot_entries;//根目录项数,供FAT12/16使用
intsmall_sector; //小扇区簇
charmedia_descriptor; //媒体描述符
intsectors_per_FAT; //每FAT扇区数,供FAT12/16使用
intsectors_per_track; //每道扇区数
intnumber_of_head; //磁头数
longhidden_sectors; //隐藏扇区数
longlarge_sector;//总扇区数,包含FAT32总扇区数
longsector_per_FAT32;//每FAT扇区数,供FAT32使用
int extended flag;// 扩展标志,供FAT32使用
intfile_system_version; //文件系统版本
longroot_cluster_number;//根目录簇号
intfile_system_information_sectornumber; //文件系统信息扇区号
intcopy_of_boot_sector;//备份引导扇区
char reserved[12];//保留,,供FAT32使用
};
2) 文件数据结构—支持FAT16/FAT32
struct file_{
charfilename[256];//支持长文件名
charfile_extention[3]; //文件扩展名
charfile_attribute;//属性
char reserved;
charcreate_time_10ms;//创建时间的10毫秒位
intfile_created_time;//文件创建时间
intfile_created_date;//文件创建日期
intlast_access_date;//文件最后访问日期
intfirst_cluster_number_high2bytes; //文件首簇号高16位
intrecent_modified_time;//文件最近修改时间
intrecent_modified_data;//文件最近修改日期
intfirst_cluster_number_low2bytes; //文件首簇号低16位
longfile_length;//文件长度
3) Core数据结构
struct core_{
current_folder[256];//存放当前目录
charfile_openned_flag;//标记struct file_已打开
}
6. 文件系统API函数
1. 自动格式化FAT16/32函数FAT16_filesystem_autoformat()—该函数由系统U盘启动时可调用并运行,它首先会读取U盘 0扇区MBR,判断MBR有效标记是否为0x55aa,如果MBR有效标记不为0x55aa,该函数将把U盘自动格式化为FAT16或FAT32文件系统;起用自动格式化处理,U盘上原有的数据被迫丢失,因此以安全层面考虑,建议不用此函数。
2. FAT文件系统初始化必须函数char FAT_filesystem_initialiation()—该函数是在U盘启动时调用,是文件系统初始化必须调用的函数,它将U盘中默认的几个分区的信息读入struct partition_BPB中,并初始化struct CORE。
3. 建立文件函数u8 create_file(u8 * filename)—该函数调用可在u盘上建立一个文件,文件名和路径通过参数char *filename指定;
4. 目录建立函数u8 create_floder(u8 * foldername)—该函数调用可在u盘上建立一个目录,目录名和路径通过参数char *foldername指定;
5. 重命名文件函数u8 rename_file(u8 * oldfilename,u8 * newfilename)—该函数用于U盘上的一个文件重命名,原文件由参数u8 * oldfilename指定,新文件名由参数u8* newfilename指定;
6. 打开文件函数u8 open_file(u8 * filename)—该函数用于在U盘上的打开一个文件,文件名通过参数u8 * filename指定,打开文件成功,返回值为文件操作句柄FCBsn(FCB sequential number),或0xff—打开文件错误,在打开错误情况下,建议先使用close_file关闭一个打开的文件后再执行打开文件。
7. 关闭文件函数u8 close_file(u8 FCBsn)—该函数调用关闭一个已打开的文件,并释放文件占用的文件句柄,文件句柄由FCBsn指定。
8. 改变当前目录函数u8cd_folder(u8 * foldername,u8 mode)—该函数用于改变文件系统的当前目录,目录改变至由参数u8 * foldername指定。函数并有两种的模式各为:1)参数mode= 0:--进入目录;2)参数mode=1--返回上层目录。
9. 文件读写位置定位函数u8 f_seek(u8FCBsn, s32 offset, u8 origin)—该函数用于文件读写当前位置的设定定位;FCBsn –是需要操作文件的文件打开句柄;offset--相对origin起始外位置偏移量;origin 指定位置移动的起始外位置,其起始外位置共有三个: SEEK_SET(0) 文件开始位置SEEK_CUR(1) 文件当前位置SEEK_END(2) 文件结束位置。
10. 文件读取函数u16 read_file(u8 FCBsn,8* buffer, u16length)—该函数用于打开的文件当前位置去读取一个指定的长度的一串数据,读取数据将存放在缓冲区buffer内,读取数据长度可由参数u16 length指定,缓冲区的首地址可由参数u8 * buffer指定,该函数返回是读取成功的总共字节数;
11. 文件写入函数u16 write_file(u8 FCBsn,u8* buffer, u16length)- 该函数实现将缓冲区buffer内的指定长度的数据去写入一个打开文件的当前位置,,写入数据长度由参数u16length指定,缓冲区首地址由参数char* buffer指定,函数返回值为成功写入的数据字节数;
12. 目录遍历函数u8 folder_enumeration(u8 *return_string,u8mode,u8 *ATTR)—该函数用于遍历u盘当前目录下所有的文件和目录,调用一次将返回一个文件或目录,同时定义了二种遍历模式,mode(0)-调用后将复位到目录的第一个文件或目录重新开始,mode(1)-继续上一次遍历目录项,遍历模式由参数charmode传递,遍历返回的文件项目录名存储于缓冲区中,其首地址由参数u8*return_string指定,返回文件目录项的类型由u8*ATTR传递,其值是返回文件或目录directoryentry的attribute字段;
13. U盘整盘遍历函数u8disk_enumeration(u8 disk_,u8 *return_string,u8 mode,u8* ATTR)—该函数可以用于遍历指定U盘整盘下所有的文件与目录,一次调用返回一个文件或目录,同时定义了二种遍历模式,mode(0)-调用后将复位到目录的第一个文件或目录重新开始遍历,mode(1)-继续上一次遍历的目录项,被枚举磁盘ID(ID编号由0开始,到Maximum_Disks – 1)由参数u8 disk_指定,遍历的模式由参数charmode指定,遍历返回的文件或目录名存储于缓冲区中,其首地址由参数u8 *return_string指定,返回文件目录项的类型由u8 *ATTR传递,其值是返回文件或目录directory entry的attribute字段; 文件系统遍历算法使用专利的《深度优先算法》。
14. 删除文件函数-- u8 delete_file(u8 *filename)—该函数用于删除U盘上的一个文件,删除的文件名通过参数char*filename指定。
15. 删除目录函数-- u8 delete_folder(u8 * foldername)—该函数用于删除u盘上的一个目录,删除目录名通过参数u8 *foldername指定,被删除目录必须是空的目录;
16. 文件查找函数—u8 find_file(u8 * filename,u8 mode, u8* folder_name )—查找文件函数支持2种模式:1)mode = 0:当前目录下查找;2)mode=1:在U盘内查找;查找文件名通过参数char * filename指定,查找模式通过参数u8 mode指定,查找成功后文件名加上其所在目录的完整路径名的字符串通过参数folder_name返回。
17. 查询分区容量和剩余容量函数—u8 volume_inquiry(u8 partition_id,u32 *volume_capacity, u32 *volume_free_space);—该函数用来查询可指定分区分区容量和剩余空间,分区号请通过参数u8partition_id指定,查询结果的分区容量将存入在参数u32 *volume_capacity,查询结果的剩余容量将存入在参数u32 *volume_free_space。
7. 例程
1)使用volume_inquiry(),获取分区容量和分区剩余容量
volume_inquiry('c',&cc,&bb);
printf("Volume C Capacity: %ld\n",cc);
printf("Volume C FreeSpace: %ld\n",bb);
2)在当前目录{C:\\}之下建立目录:CREATE_FOLDER_TEST
create_floder("CREATE_FOLDER_TEST");
3)在目录CREATE_FOLDER_TEST之下建立文件:created_file.txt
create_file("C:\\CREATE_FOLDER_TEST\\created_file.txt");
4)进入目录d:\\CREATE_FOLDER_TEST,并打印目录d:\\CREATE_FOLDER_TEST的所有文件!
cd_folder("d:\\CREATE_FOLDER_TEST",0);
mode = 0;
while(folder_enumeration(buf,mode,&ATTR) == SUCC)
{
printf("\nreaded entry=%s Attr = %x",buf,ATTR);
mode = 1;
}
5)返回根目录,并打印根目录下的所有文件
cd_folder(" ",1);
mode = 0;
while(folder_enumeration(buf,mode,&ATTR) == SUCC)
{
printf("\nreaded entry=%s Attr = %x",buf,ATTR);
mode = 1;
}
6)DISK0 被 拷贝至DISK1
mode = 0; //设置disk_enumeration列举mode(0)-复位至第一个文件项或目录项开始枚举
while(disk_enumeration(0,buf,mode,&ATTR)== SUCC) //枚举一个目录项或目录项
{
printf("\nreaded entry=%s Attr =%x",buf,ATTR); //打印被枚举的一个目录项或目录项
if(mode == 0)
mode = 1;//设置disk_enumeration列举mode(1)- 继续上一枚举后的目录项或目录项
if(ATTR & ATTR_DIRECTORY)
{
buf[0]++; //盘符由C加1,成为D
create_floder(buf); //建一个disk_enumeration的目录
continue;
}
else //复制文件
{ HANDLE1 = open_file(buf); //打开文件
buf[0]++; //盘符由C加1,成为D
create_file(buf); //在DISK1上建立文件,
}
if (HANDLE1 != FAIL)
{HANDLE2 = open_file(buf); //打开DISK1上建立的文件
do{ //复制文件
cc = read_file(HANDLE1,buf+400,50000); //读文件
printf("\nreaded chars = %ld",cc); //打印读文件读取的字节数
write_file(HANDLE2,buf+400,cc); //将读取的字节写去DISK1上的文件
if(cc != 50000) //检查读取的字节数,确认文件尾
{
close_file(HANDLE1); //文件复制结束,关闭文件
close_file(HANDLE2);
break;
}
}while(1);
}
else
{
printf("Openfile failed!");
}
}
{
printf("Openfile failed!");
}
}
| 欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |