找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3534|回复: 0
收起左侧

嵌入式FAT16/32文件系统 全面了解

[复制链接]
ID:140343 发表于 2016-10-21 13:04 | 显示全部楼层 |阅读模式
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]++;                                          //盘符由C1,成为D
       create_floder(buf);                            //建一个disk_enumeration的目录
       continue;
      }
      else                                                           //复制文件
     { HANDLE1 = open_file(buf);                                      //打开文件
       buf[0]++;                                          //盘符由C1,成为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!");
     }
  }

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表