历史上的今天
返回首页

历史上的今天

今天是:2024年10月24日(星期四)

正在发生

2019年10月24日 | 嵌入式FAT16/32文件系统 全面了解

2019-10-24 来源:51hei

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: %ldn",cc);

printf("Volume C FreeSpace: %ldn",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!");

推荐阅读

史海拾趣

Deutron Electronics Corp公司的发展小趣事

随着环保意识的日益提高,Deutron Electronics Corp也积极响应环保号召,致力于实现绿色生产和可持续发展。公司采用环保材料和生产工艺,减少了对环境的污染。同时,公司还加大了对节能减排的投入,提高了资源利用效率。这些努力使得Deutron Electronics Corp在行业内树立了良好的环保形象,也为公司的长期发展奠定了坚实基础。

Habia Cable公司的发展小趣事

Deutron Electronics Corp深知研发和创新对于公司发展的重要性。因此,公司始终保持着对研发的高投入,不断引进和培养人才。公司建立了完善的研发体系,鼓励员工参与创新活动,并为他们提供了充足的资源和支持。这些措施使得Deutron Electronics Corp在研发方面取得了显著成果,为公司的发展提供了源源不断的动力。

EHC(ELECTRONICHARDWARE)公司的发展小趣事

在电子行业中,产品质量是企业生存和发展的关键。EHC公司深知这一点,因此一直将品质管理作为企业发展的重要战略。公司建立了完善的质量管理体系,从原材料采购到生产制造再到产品出厂,每一个环节都经过严格的把控。这种对品质的坚持和追求让EHC公司的产品在市场上赢得了广泛的信任和认可。

贝特莱公司的发展小趣事

贝特莱与小米的合作是其发展历程中的又一重要事件。作为小米全系列合作伙伴,贝特莱为米家智能门锁提供了独家指纹传感器和定制算法芯片。随着米家智能门锁销量突破百万大关,贝特莱也实现了销售上的重大突破。这一合作不仅证明了贝特莱技术的成熟与可靠,也进一步提升了其在智能门锁市场的地位。

Axiomtek公司的发展小趣事

深圳贝特莱电子科技股份有限公司成立于2011年7月,从一开始,公司就明确了以技术研发为核心的发展战略。依托专业团队多年的行业资源积累,贝特莱致力于开发具有自主知识产权的核心技术。在指纹识别、触控、生命感知及MCU等芯片领域,贝特莱不断取得突破,为后续的市场拓展奠定了坚实的基础。

Abbatron公司的发展小趣事

Abbatron公司深知合作的重要性,积极寻求与业内其他企业的合作机会。通过与某知名电子制造商的合作,Abbatron公司成功将其创新技术应用于实际产品中,进一步扩大了市场份额。这种合作模式不仅促进了双方的发展,也为整个电子行业带来了更多的可能性。

问答坊 | AI 解惑

在wince开发程序遇到了问题,个人判断应该是unicode 编码问题

在wince开发程序遇到了问题,个人判断应该是unicode 编码问题,比如有如下问题; CString a(\"$ABCDE\"); 个人认为a.left(6)应该是=\"$ABCDE\",结果返回值是\"$\",难道CString 不支持unicode?,left函数参数不应该是字符数量吗? 另外希望本人自己 ...…

查看全部问答>

OMAP5912 DMA数据没传到目的地址里面

首先,我用kmalloc(30*sizeof(char),GFP_DMA)分配了两段存储空间,分别作为源地址和目的地址,就是想要通过dma方式把源地址的数据传送到目的地址。 我采用的是信道0,设置了其相应寄存器, (源地址和目的地址寄存器的值是通过 virt_to_phys(mem) ...…

查看全部问答>

COM口资源释放

我在做一个拨号程序,在进行长时间拨号后(同时做数据业务),发现拨号不成功,返回的错误码是COM口被其他程序占用了, 但是这个时候没有其他程序占用COM口,拨号也已经挂断, 我用超级终端打开后发现可以打开COM口, 但是COM口对操作没有任何反应 ...…

查看全部问答>

国内电子书企业 升级还是“等死”

本帖最后由 jameswangsynnex 于 2015-3-3 19:59 编辑 中国互联网巨头盛大推出的电子书内测价格让整个电子阅读器产业感到了前所未有的“寒意”,而友达大规模进军电子书屏幕市场使得电子书屏幕一直被一家企业垄断的格局即将被打破,加上其他企业也 ...…

查看全部问答>

我买电子元器件的经验分享

  今天闲来没事,突然有写点东西的冲动。写什么呢,从大三开始入手学习电子技术,从最开始的51单片机开始学起,一步一步爬到现在,学DSP,学专用芯片。多多少少积累了点经验,今天就说说购买元器件吧,关于这点很早就想说说。  &nbs ...…

查看全部问答>

大侠们,救命啊,小弟有关于dsp的问题,请大家解答

小弟最近在做dsp5509向sd卡写入速度的测试实验,可是实验结果相当的不理想,要么是写的数据不完整,要么是写入速度太慢了,用的芯片是5509.有没有哪位大侠做过相关这方面的测试,能和小弟交流下么qq:106703178email:lovejy984@163.com不胜感激啊 ...…

查看全部问答>

TI的消费电子的电源管理方案

简述: 德州仪器 (TI) 电源管理 IC有着各种解决方案。其中TPS65053x 是集成型电源管理 IC,面向那些由单节锂离子电池或锂聚合物电池供电、需要多个电源轨的应用。TPS65053X 在转换器提供了高达1A的输 图1 IC架构 主要特性: TPS65053x 是集成 ...…

查看全部问答>

高端指纹锁能否促进门禁系统发展

  指纹锁作为门禁识别的衍生产品,依赖于生物识别的技术发展,国外已经逐步兴起进入更多的家庭当中。对于我们国内市场而言,指纹锁的普及率远不及它的名声那样红火。然而对于安防市场,指纹锁仍有可爆发的市场潜力,随着科技的不断进步,高端指纹 ...…

查看全部问答>

电子罗盘

怎么用电子罗盘读回的数据转换为角度信息…

查看全部问答>