📄 fat.c
字号:
//---------------------------- 文件系统程序 -----------------------------
//
//文件系统:简易FAT32
//代码作者:廖华明(师兄)
//时间:2009.7.8
//
//------------------------------------------------------------------------
#include"fat.h"
uint32 SearchFile_Clust;
uint32 Music_Dir;
uint32 fclust[20];
uint8 fcount;
uint32 fsize[20];
uint32 NextCluster; //指向当前正在读取文件的簇号
uint32 SectorIndex=0; //正在读扇区
uint32 Partition_StartLBA; // 该分区内第一个扇区地址
uint16 BPB_BytesPerSec; //扇区字节数
uint8 BPB_SecPerClus; //每簇扇区数
uint16 BPB_RsvdSecCnt; //保留扇区数
uint8 BPB_NumFATs; //FAT数目
uint16 BPB_RootEntCnt; //根目录项数 0
uint16 BPB_TotSec16; //小扇区总数 0
uint8 BPB_Media; //媒体描述符
uint16 BPB_FATSz16; //每FAT扇区数fat32不用为0
uint16 BPB_SecPerTrk; //每道扇区数
uint16 BPB_NumHeads; //磁头数
uint32 BPB_HiddSec; //隐藏扇区数
uint32 BPB_TotSec32; //总扇区数
uint32 BPB_FATSz32; //每FAT扇区数fat32
uint16 BPB_ExtFlags; //fat32扩展标志
uint16 BPB_FSVer; //fat32特有,高位为fat32的主版本号,底位为次版本号
uint32 BPB_RootClus; //根目录簇号
uint16 BPB_FSInfo; //文件系统信息扇区号
uint16 BPB_BKBootSec; //引导扇区备份号
uint8 deName[8];
uint8 deExtension[3];
uint32 Clust; //当前目录的簇号
uint16 Nums; //仅FAT12—FAT16中的根目录区有效
uint32 Index; //当前的BLOCK中目录项索引
uint32 FileSize; //文件长度
uint32 FAT1Sec; //FAT1表的位置
uint32 FAT2Sec;
uint32 FirstDataSector; //第一个根目录位置,区号为2
uint32 FirstDirSector;
uint8 Fat_Buffer[512];
uint32 FAT_MASK;
uint16 RootDirEnts; // 根目录总的项数(FAT12&FAT16)
uint8 Fat_Init(void)
{
uint32 temp;
SD_ReadBlock(0,Fat_Buffer);
Partition_StartLBA = (Fat_Buffer[454]|(Fat_Buffer[455]<<8)|((uint32)Fat_Buffer[456]<<16)|((uint32)Fat_Buffer[457]<<24));
SD_ReadBlock(Partition_StartLBA,Fat_Buffer); //FAT32 read BPB
BPB_BytesPerSec = Fat_Buffer[11] |(Fat_Buffer[12] << 8); //0x0200 //每个扇区字节数
BPB_SecPerClus = Fat_Buffer[13]; //0x08 //每个簇的扇区数
BPB_RsvdSecCnt = Fat_Buffer[14] |(Fat_Buffer[15] << 8); //0x20 //保留扇区数
BPB_NumFATs = Fat_Buffer[16]; //0x02 //FAT 表数目
BPB_RootEntCnt = Fat_Buffer[17] | (Fat_Buffer[18] << 8);
BPB_TotSec16 = Fat_Buffer[19] | (Fat_Buffer[20] << 8);
BPB_Media = Fat_Buffer[21];
BPB_FATSz16 = Fat_Buffer[22] | (Fat_Buffer[23] << 8);
BPB_SecPerTrk = Fat_Buffer[24] | (Fat_Buffer[25] << 8);
BPB_NumHeads = Fat_Buffer[26] | (Fat_Buffer[27] << 8);
BPB_HiddSec = Fat_Buffer[28] | (Fat_Buffer[29] << 8) | ((uint32)Fat_Buffer[30] << 16) | ((uint32)Fat_Buffer[31] << 24);
BPB_TotSec32 = Fat_Buffer[32] | (Fat_Buffer[33] << 8) | ((uint32)Fat_Buffer[34] << 16) | ((uint32)Fat_Buffer[35] << 24);
BPB_FATSz32 = Fat_Buffer[36] | (Fat_Buffer[37] << 8) | ((uint32)Fat_Buffer[38] << 16) | ((uint32)Fat_Buffer[39] << 24);
BPB_ExtFlags = Fat_Buffer[40] | (Fat_Buffer[41] << 8);
BPB_FSVer = Fat_Buffer[42] | (Fat_Buffer[43] << 8);
BPB_RootClus = Fat_Buffer[44] | (Fat_Buffer[45] << 8) | ((uint32)Fat_Buffer[46] << 16) | ((uint32)Fat_Buffer[47] << 24);
BPB_FSInfo = Fat_Buffer[48] | (Fat_Buffer[49] << 8);
BPB_BKBootSec = Fat_Buffer[50] | (Fat_Buffer[51] << 8);
FAT_MASK = FAT32_MASK; //0x0fffffff
Clust = BPB_RootClus;
FAT1Sec = BPB_RsvdSecCnt+Partition_StartLBA;
FAT2Sec = FAT1Sec+BPB_FATSz32;
FirstDataSector = FAT2Sec+BPB_FATSz32;
return 1;
}
uint8 FileExt_Compare(uint8 *strExt1,uint8 *strExt2)
{
uint8 i;
for(i=0; i<3; i++)
{
if(strExt1[i]!= strExt2[i]) break;
}
if(i == 3) return 1;
return 0;
}
uint8 FileName_Compare(uint8 *strName1,uint8 *strName2)
{
uint8 i;
for(i=0; i<4; i++)
{
if(strName1[i]!= strName2[i]) break;
}
if(i == 4) return 1;
return 0;
}
void SearchFileOfName(uint32 TargetStartSector,uint8 *File_Name)
{
uint8 i;
uint32 tem;
uint32 Index_tmp=0;
do{
SD_ReadBlock(TargetStartSector + Index_tmp/(BPB_BytesPerSec/32),Fat_Buffer); // 重新读取目录表
tem=((Index_tmp)*32)%BPB_BytesPerSec;
if((Fat_Buffer[tem+11] & ATTR_LONG_FILENAME) != ATTR_LONG_FILENAME); // 是否是长文件名
{
if((Fat_Buffer[tem] != 0xe5) && (Fat_Buffer[tem] != 0x05)) //文件没有删除
{
for(i=0;i<8;i++)
{
deName[i]=Fat_Buffer[tem+i];
}
if(FileName_Compare(File_Name,deName))
{
SearchFile_Clust = ((uint32)Fat_Buffer[tem+20]<<16) | ((uint32)Fat_Buffer[tem+21]<<24) | (Fat_Buffer[tem+26]) | (Fat_Buffer[tem+27]<<8);
Index_tmp++;
break;
}
}
}
Index_tmp++;
if(Fat_Buffer[tem] == 0) // 等所有文件都已经查询完了
{
Index_tmp=0;
break;
}
}
while(1);
}
void SearchFileOfExt(uint32 TargetStartSector,uint8*Ext)
{
uint8 i;
uint32 tem;
do{
SD_ReadBlock(TargetStartSector + Index/(BPB_BytesPerSec/32),Fat_Buffer); // 重新读取目录表
tem=((Index)*0x20)%BPB_BytesPerSec;
if((Fat_Buffer[tem+11] & ATTR_LONG_FILENAME) != ATTR_LONG_FILENAME); // 是否是长文件名
{
if((Fat_Buffer[tem] != 0xe5) && (Fat_Buffer[tem] != 0x05)) //文件没有删除
{
if((Fat_Buffer[tem+11]&ATTR_DIRECTORY) != ATTR_DIRECTORY) // is it a directory ?
{
for(i=0;i<8;i++)
{
deName[i]=Fat_Buffer[tem+i];
}
for(i=0;i<3;i++)
{
deExtension[i]=Fat_Buffer[tem+8+i];
}
if(FileExt_Compare(deExtension,Ext))
{
Clust=((uint32)Fat_Buffer[tem+20]<<16) | ((uint32)Fat_Buffer[tem+21]<<24) | (Fat_Buffer[tem+26]) | (Fat_Buffer[tem+27]<<8);
FileSize=(Fat_Buffer[tem+28]) | (Fat_Buffer[tem+29]<<8)|((uint32)Fat_Buffer[tem+30]<<16)|((uint32)Fat_Buffer[tem+31]<<24);
Index++;
break;
}
}
}
}
Index++;
if(Fat_Buffer[tem] == 0) // 等所有文件都已经查询完了
{
Index=0;
break;
}
}
while(1);
}
uint32 ReadBlockforCluster(uint32 Sector,uint32 offset)
{
uint32 tmp;
SD_ReadBlock(Sector,Fat_Buffer);
tmp=Fat_Buffer[offset] |(Fat_Buffer[offset+1]<<8) |((uint32)Fat_Buffer[offset+2]<<16) |((uint32)Fat_Buffer[offset+3]<<24);
return tmp;
}
uint32 FatNextCluster(uint32 cluster)
{
uint32 nextCluster=0;
uint32 fatOffset=0;
uint32 sector=0;
uint16 offset=0;
fatOffset = cluster << 2;
sector = FAT1Sec + (fatOffset>>9); // 计算FAT扇区号
offset = fatOffset % BPB_BytesPerSec; // 计算FAT扇区号中表项的偏移地址
nextCluster = ReadBlockforCluster(sector,offset); // 读取下一个簇号
if (nextCluster >= (CLUST_EOFS & FAT_MASK)) // 是否文件的结束簇
{
nextCluster = CLUST_EOFE;
}
return nextCluster;
}
void GetMusicFile(void)
{
fcount=0;
SearchFileOfName(FirstDataSector,"音乐");
Music_Dir=FirstDataSector+(SearchFile_Clust - 2)*8;
while(1)
{
SearchFileOfExt(Music_Dir,"MP3");
if(Index==0) break;
fclust[fcount]=Clust;
fsize[fcount]=FileSize;
fcount++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -