標題: 嵌入式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.raoushi.com/bbs/) |
Powered by Discuz! X3.1 |