找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 4353|回復(fù): 0
收起左側(cè)

嵌入式FAT16/32文件系統(tǒng) 全面了解

[復(fù)制鏈接]
ID:140343 發(fā)表于 2016-10-21 13:04 | 顯示全部樓層 |閱讀模式
1. 總則
本文件系統(tǒng)完全兼容FAT16/FAT32文件系統(tǒng)總共兩種格式,兼容長(zhǎng)文件名,兼容文字編碼GB2312/UNICODE漢字編碼(文件名完全支持中文),實(shí)現(xiàn)了支持子目錄,實(shí)現(xiàn)了支持文件的讀取,寫(xiě)入,刪除,創(chuàng)建等文件系統(tǒng)常用功能?傊,本文件系統(tǒng)代碼全部使用C代碼編寫(xiě),可以移植去各種單片機(jī)平臺(tái)上面實(shí)現(xiàn)文件系統(tǒng)模塊。
2. 文件系統(tǒng)支持路徑字符串的原則
1)  盤(pán)符原則
a)  盤(pán)符原則,盤(pán)符命名由C開(kāi)始,到Z結(jié)束
2)  文件名原則(長(zhǎng)文件名的長(zhǎng)度不超過(guò)250字符的字節(jié))
a)  文件名可是文件名與擴(kuò)展名混合組成, 1)短文件名不要超過(guò)8個(gè)字節(jié),長(zhǎng)文件名不要超過(guò)250字節(jié) 2)擴(kuò)展名一般不要超過(guò)3個(gè)字節(jié)
b)  文件名首字符不要為數(shù)字
c)  文件名的字符串大小寫(xiě)不作區(qū)分
3. 文件系統(tǒng)功能論據(jù)
1)  該文件系統(tǒng)完全兼容FAT16/FAT32文件系統(tǒng)總共兩種格式,兼容長(zhǎng)文件名,兼容文字編碼GB2312/UNICODE漢字編碼(文件名完全支持中文),實(shí)現(xiàn)了支持子目錄,實(shí)現(xiàn)了支持文件的讀取,寫(xiě)入,刪除,創(chuàng)建等文件系統(tǒng)常用功能。
2)  本文件系統(tǒng)代碼全部使用C代碼編寫(xiě),代碼可以移植去各種單片機(jī)平臺(tái)上面實(shí)現(xiàn)文件系統(tǒng)模塊運(yùn)行。在單片機(jī)上運(yùn)行程序員要把磁盤(pán)虛擬驅(qū)動(dòng)替換為SD卡或者磁盤(pán)驅(qū)動(dòng)。
3)  本文件系統(tǒng)代碼實(shí)現(xiàn)了文件讀寫(xiě)緩沖:文件內(nèi)存緩沖越大,文件讀寫(xiě)越快,其大小可以用編譯宏EnableFileBuf,TotalFileBUFsQTYeachFCB,F(xiàn)ileBUFSize來(lái)設(shè)置(在配置文件fat_cfg.h中)。
4. 文件系統(tǒng)源代碼文件說(shuō)明舉例
1)  fat.c—文件系統(tǒng)代碼
2)  fat.h—文件系統(tǒng)函數(shù)聲明文件
3)  Fat_cfg.h—配置文件文件系統(tǒng)
4)  Types.h—文件系統(tǒng)數(shù)據(jù)類型重替換的文件
5)  Flash_management.c—磁盤(pán)虛擬驅(qū)動(dòng)
6)  Time.c—RTC實(shí)時(shí)時(shí)鐘的驅(qū)動(dòng)文件,文件存儲(chǔ),修改,創(chuàng)建時(shí)間提供

5. 文件系統(tǒng)重要占用內(nèi)存數(shù)據(jù)結(jié)構(gòu)(僅供參考,實(shí)際情況請(qǐng)參考配置文件fat_cfg.h)
1)  分區(qū)數(shù)據(jù)結(jié)構(gòu)—支持FAT16/FAT32
   structpartition_BPB{
   charpartition_id; //從C開(kāi)始到Z結(jié)束
   char system_id;//分區(qū)類型  0C-FAT32,06-FAT16 ect..
   long relative_sector;//分區(qū)起始扇區(qū)號(hào)
   longtotal_sector;   //分區(qū)總扇區(qū)數(shù)
   intbytes_per_sector;//每扇區(qū)字節(jié)數(shù)
   charsector_per_cluster; //每簇扇區(qū)數(shù)
   int reservedsector;  //保留扇區(qū)數(shù)
   charnumbers_of_FAT;//FAT副本數(shù)
   intboot_entries;//根目錄項(xiàng)數(shù),供FAT12/16使用
   intsmall_sector; //小扇區(qū)簇
   charmedia_descriptor; //媒體描述符
   intsectors_per_FAT; //每FAT扇區(qū)數(shù),供FAT12/16使用
   intsectors_per_track; //每道扇區(qū)數(shù)
   intnumber_of_head; //磁頭數(shù)
   longhidden_sectors; //隱藏扇區(qū)數(shù)
   longlarge_sector;//總扇區(qū)數(shù),包含F(xiàn)AT32總扇區(qū)數(shù)
   longsector_per_FAT32;//每FAT扇區(qū)數(shù),供FAT32使用
   int extended flag;// 擴(kuò)展標(biāo)志,供FAT32使用
   intfile_system_version; //文件系統(tǒng)版本
   longroot_cluster_number;//根目錄簇號(hào)
   intfile_system_information_sectornumber; //文件系統(tǒng)信息扇區(qū)號(hào)
   intcopy_of_boot_sector;//備份引導(dǎo)扇區(qū)
       char reserved[12];//保留,,供FAT32使用
       };
2)  文件數(shù)據(jù)結(jié)構(gòu)—支持FAT16/FAT32
   struct file_{
   charfilename[256];//支持長(zhǎng)文件名
   charfile_extention[3]; //文件擴(kuò)展名
   charfile_attribute;//屬性
   char reserved;
   charcreate_time_10ms;//創(chuàng)建時(shí)間的10毫秒位
   intfile_created_time;//文件創(chuàng)建時(shí)間
   intfile_created_date;//文件創(chuàng)建日期
   intlast_access_date;//文件最后訪問(wèn)日期
   intfirst_cluster_number_high2bytes; //文件首簇號(hào)高16位
   intrecent_modified_time;//文件最近修改時(shí)間
   intrecent_modified_data;//文件最近修改日期
   intfirst_cluster_number_low2bytes; //文件首簇號(hào)低16位
   longfile_length;//文件長(zhǎng)度
3)   Core數(shù)據(jù)結(jié)構(gòu)
   struct core_{
  current_folder[256];//存放當(dāng)前目錄
   charfile_openned_flag;//標(biāo)記struct file_已打開(kāi)
   }
6. 文件系統(tǒng)API函數(shù)
1.   自動(dòng)格式化FAT16/32函數(shù)FAT16_filesystem_autoformat()—該函數(shù)由系統(tǒng)U盤(pán)啟動(dòng)時(shí)可調(diào)用并運(yùn)行,它首先會(huì)讀取U盤(pán) 0扇區(qū)MBR,判斷MBR有效標(biāo)記是否為0x55aa,如果MBR有效標(biāo)記不為0x55aa,該函數(shù)將把U盤(pán)自動(dòng)格式化為FAT16或FAT32文件系統(tǒng);起用自動(dòng)格式化處理,U盤(pán)上原有的數(shù)據(jù)被迫丟失,因此以安全層面考慮,建議不用此函數(shù)。

2.  FAT文件系統(tǒng)初始化必須函數(shù)char FAT_filesystem_initialiation()—該函數(shù)是在U盤(pán)啟動(dòng)時(shí)調(diào)用,是文件系統(tǒng)初始化必須調(diào)用的函數(shù),它將U盤(pán)中默認(rèn)的幾個(gè)分區(qū)的信息讀入struct partition_BPB中,并初始化struct CORE。

3.   建立文件函數(shù)u8 create_file(u8 * filename)—該函數(shù)調(diào)用可在u盤(pán)上建立一個(gè)文件,文件名和路徑通過(guò)參數(shù)char *filename指定;

4.   目錄建立函數(shù)u8 create_floder(u8 * foldername)—該函數(shù)調(diào)用可在u盤(pán)上建立一個(gè)目錄,目錄名和路徑通過(guò)參數(shù)char *foldername指定;
5.   重命名文件函數(shù)u8 rename_file(u8 * oldfilename,u8 * newfilename)—該函數(shù)用于U盤(pán)上的一個(gè)文件重命名,原文件由參數(shù)u8 * oldfilename指定,新文件名由參數(shù)u8* newfilename指定;

6.   打開(kāi)文件函數(shù)u8 open_file(u8 * filename)—該函數(shù)用于在U盤(pán)上的打開(kāi)一個(gè)文件,文件名通過(guò)參數(shù)u8 * filename指定,打開(kāi)文件成功,返回值為文件操作句柄FCBsn(FCB sequential number),或0xff—打開(kāi)文件錯(cuò)誤,在打開(kāi)錯(cuò)誤情況下,建議先使用close_file關(guān)閉一個(gè)打開(kāi)的文件后再執(zhí)行打開(kāi)文件。

7.  關(guān)閉文件函數(shù)u8 close_file(u8 FCBsn)—該函數(shù)調(diào)用關(guān)閉一個(gè)已打開(kāi)的文件,并釋放文件占用的文件句柄,文件句柄由FCBsn指定。
8.  改變當(dāng)前目錄函數(shù)u8cd_folder(u8 * foldername,u8 mode)—該函數(shù)用于改變文件系統(tǒng)的當(dāng)前目錄,目錄改變至由參數(shù)u8 * foldername指定。函數(shù)并有兩種的模式各為:1)參數(shù)mode= 0:--進(jìn)入目錄;2)參數(shù)mode=1--返回上層目錄。

9.   文件讀寫(xiě)位置定位函數(shù)u8 f_seek(u8FCBsn, s32 offset, u8 origin)—該函數(shù)用于文件讀寫(xiě)當(dāng)前位置的設(shè)定定位;FCBsn –是需要操作文件的文件打開(kāi)句柄;offset--相對(duì)origin起始外位置偏移量;origin 指定位置移動(dòng)的起始外位置,其起始外位置共有三個(gè): SEEK_SET(0) 文件開(kāi)始位置SEEK_CUR(1) 文件當(dāng)前位置SEEK_END(2) 文件結(jié)束位置。
10.  文件讀取函數(shù)u16 read_file(u8 FCBsn,8* buffer, u16length)—該函數(shù)用于打開(kāi)的文件當(dāng)前位置去讀取一個(gè)指定的長(zhǎng)度的一串?dāng)?shù)據(jù),讀取數(shù)據(jù)將存放在緩沖區(qū)buffer內(nèi),讀取數(shù)據(jù)長(zhǎng)度可由參數(shù)u16 length指定,緩沖區(qū)的首地址可由參數(shù)u8 * buffer指定,該函數(shù)返回是讀取成功的總共字節(jié)數(shù);
11.  文件寫(xiě)入函數(shù)u16 write_file(u8 FCBsn,u8* buffer, u16length)- 該函數(shù)實(shí)現(xiàn)將緩沖區(qū)buffer內(nèi)的指定長(zhǎng)度的數(shù)據(jù)去寫(xiě)入一個(gè)打開(kāi)文件的當(dāng)前位置,,寫(xiě)入數(shù)據(jù)長(zhǎng)度由參數(shù)u16length指定,緩沖區(qū)首地址由參數(shù)char* buffer指定,函數(shù)返回值為成功寫(xiě)入的數(shù)據(jù)字節(jié)數(shù);
12.  目錄遍歷函數(shù)u8 folder_enumeration(u8 *return_string,u8mode,u8 *ATTR)—該函數(shù)用于遍歷u盤(pán)當(dāng)前目錄下所有的文件和目錄,調(diào)用一次將返回一個(gè)文件或目錄,同時(shí)定義了二種遍歷模式,mode(0)-調(diào)用后將復(fù)位到目錄的第一個(gè)文件或目錄重新開(kāi)始,mode(1)-繼續(xù)上一次遍歷目錄項(xiàng),遍歷模式由參數(shù)charmode傳遞,遍歷返回的文件項(xiàng)目錄名存儲(chǔ)于緩沖區(qū)中,其首地址由參數(shù)u8*return_string指定,返回文件目錄項(xiàng)的類型由u8*ATTR傳遞,其值是返回文件或目錄directoryentry的attribute字段;

13.  U盤(pán)整盤(pán)遍歷函數(shù)u8disk_enumeration(u8 disk_,u8 *return_string,u8 mode,u8* ATTR)—該函數(shù)可以用于遍歷指定U盤(pán)整盤(pán)下所有的文件與目錄,一次調(diào)用返回一個(gè)文件或目錄,同時(shí)定義了二種遍歷模式,mode(0)-調(diào)用后將復(fù)位到目錄的第一個(gè)文件或目錄重新開(kāi)始遍歷,mode(1)-繼續(xù)上一次遍歷的目錄項(xiàng),被枚舉磁盤(pán)ID(ID編號(hào)由0開(kāi)始,到Maximum_Disks – 1)由參數(shù)u8 disk_指定,遍歷的模式由參數(shù)charmode指定,遍歷返回的文件或目錄名存儲(chǔ)于緩沖區(qū)中,其首地址由參數(shù)u8 *return_string指定,返回文件目錄項(xiàng)的類型由u8 *ATTR傳遞,其值是返回文件或目錄directory entry的attribute字段; 文件系統(tǒng)遍歷算法使用專利的《深度優(yōu)先算法》。
14.  刪除文件函數(shù)-- u8 delete_file(u8 *filename)—該函數(shù)用于刪除U盤(pán)上的一個(gè)文件,刪除的文件名通過(guò)參數(shù)char*filename指定。

15.  刪除目錄函數(shù)-- u8 delete_folder(u8 * foldername)—該函數(shù)用于刪除u盤(pán)上的一個(gè)目錄,刪除目錄名通過(guò)參數(shù)u8 *foldername指定,被刪除目錄必須是空的目錄;
16.  文件查找函數(shù)—u8 find_file(u8 * filename,u8 mode, u8* folder_name )—查找文件函數(shù)支持2種模式:1)mode = 0:當(dāng)前目錄下查找;2)mode=1:在U盤(pán)內(nèi)查找;查找文件名通過(guò)參數(shù)char * filename指定,查找模式通過(guò)參數(shù)u8 mode指定,查找成功后文件名加上其所在目錄的完整路徑名的字符串通過(guò)參數(shù)folder_name返回。
17.  查詢分區(qū)容量和剩余容量函數(shù)—u8 volume_inquiry(u8 partition_id,u32 *volume_capacity, u32 *volume_free_space);—該函數(shù)用來(lái)查詢可指定分區(qū)分區(qū)容量和剩余空間,分區(qū)號(hào)請(qǐng)通過(guò)參數(shù)u8partition_id指定,查詢結(jié)果的分區(qū)容量將存入在參數(shù)u32 *volume_capacity,查詢結(jié)果的剩余容量將存入在參數(shù)u32 *volume_free_space。
7. 例程
1)使用volume_inquiry(),獲取分區(qū)容量和分區(qū)剩余容量
volume_inquiry('c',&cc,&bb);
printf("Volume C Capacity: %ld\n",cc);
printf("Volume C FreeSpace: %ld\n",bb);

2)在當(dāng)前目錄{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)進(jìn)入目錄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;  //設(shè)置disk_enumeration列舉mode(0)-復(fù)位至第一個(gè)文件項(xiàng)或目錄項(xiàng)開(kāi)始枚舉
  while(disk_enumeration(0,buf,mode,&ATTR)== SUCC)       //枚舉一個(gè)目錄項(xiàng)或目錄項(xiàng)
  {
     printf("\nreaded entry=%s Attr =%x",buf,ATTR);  //打印被枚舉的一個(gè)目錄項(xiàng)或目錄項(xiàng)
     
     if(mode == 0)
       mode = 1;//設(shè)置disk_enumeration列舉mode(1)- 繼續(xù)上一枚舉后的目錄項(xiàng)或目錄項(xiàng)
      if(ATTR & ATTR_DIRECTORY)
      {
       buf[0]++;                                          //盤(pán)符由C1,成為D
       create_floder(buf);                            //建一個(gè)disk_enumeration的目錄
       continue;
      }
      else                                                           //復(fù)制文件
     { HANDLE1 = open_file(buf);                                      //打開(kāi)文件
       buf[0]++;                                          //盤(pán)符由C1,成為D
       create_file(buf);                                    //DISK1上建立文件,
      }
     if (HANDLE1 != FAIL)
     {HANDLE2 = open_file(buf);                          //打開(kāi)DISK1上建立的文件
       do{                                                           //復(fù)制文件
        cc = read_file(HANDLE1,buf+400,50000);                            //讀文件
         printf("\nreaded chars = %ld",cc);                   //打印讀文件讀取的字節(jié)數(shù)
        write_file(HANDLE2,buf+400,cc);          //將讀取的字節(jié)寫(xiě)去DISK1上的文件
         if(cc != 50000)                            //檢查讀取的字節(jié)數(shù),確認(rèn)文件尾
         {
          close_file(HANDLE1);                           //文件復(fù)制結(jié)束,關(guān)閉文件
          close_file(HANDLE2);
           break;  
         }
      }while(1);
     }
    else
     {
      printf("Openfile failed!");
     }
  }
     {
      printf("Openfile failed!");
     }
  }

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表