📄 fat.c
字号:
#include"FAT.h"
//FAT部分代码
//正点原子@SCUT
//全局变量区域
DWORD FirstDirClust; //根目录簇号
DWORD FirstDataSector; //数据区的第一个扇区
WORD BytesPerSector; //每扇区字节数
DWORD FATsectors; //FAT表所占扇区数
WORD SectorsPerClust; //每簇扇区数
DWORD FirstFATSector; //第一个FAT表(FAT1)所在扇区
DWORD FirstDirSector; //第一个目录扇区 fat32
DWORD RootDirSectors; //根目录所在扇区
DWORD RootDirCount; //根目录下目录项数
BYTE FAT32_Enable; //FAT32文件系统标志
u32 sys_ico[9]; //系统图标缓存区!不能篡改!
u32 file_ico[4]; //文件图标缓存区 folder;mus;pic;book;
const unsigned char *folder[7]=
{
"SYSTEM ",
"FONT ",
"SYSICO ",
"GAME ",
"LEVEL1 ",
"LEVEL2 ",
"LEVEL3 ",
};
//系统文件定义
const unsigned char *sysfile[15]=
{
"FONT16 FON",
"FONT12 FON",
//系统主界面图标
"MUSIC BMP",
"PICTURE BMP",
"GAME BMP",
"ALARM BMP",
"TIME BMP",
"SETTING BMP",
"TXT BMP",
"RADIO BMP",
"LIGHT BMP",
//系统文件图标 12开始
"FOLDER BMP",
"MUS BMP",
"PIC BMP",
"BOOK BMP",
};
//文件信息缓存区
FileInfoStruct F_Info[8];
//外部全局变量
//FAT 数据缓存区,不能和jpg_buffer共用.否则在FAT32文件系统里面,可能出错!!
u8 fat_buffer[512];
u8 LongNameBuffer[MAX_LONG_NAME_SIZE];//长文件名的缓存区
BOOL LongNameFlag = 0;//是否存在长文件名的标志
//显示一次数据流
void show_data(u8 *p,u16 num)
{
u16 i=0;
printf("TEMP DATA:\n");
delay_ms(1000);
for(i=0;i<num;i++)printf(" %x",*p++);
printf("\ndata over\n");
}
//FAT初始化,不含SD的初始化,用之前应先调用sd的初始化
unsigned char FAT_Init(void)//Initialize of FAT need initialize SD first
{
bootsector710 *bs = 0;
bpb710 *bpb = 0;
partrecord *pr = 0;
DWORD hidsec=0;
DWORD Capacity;
Capacity = SD_GetCapacity();
if(Capacity<0xff)return 1;
if(SD_ReadSingleBlock(0,fat_buffer))return 1;
bs = (bootsector710 *)fat_buffer;
pr = (partrecord *)((partsector *)fat_buffer)->psPart;//first partition
hidsec = pr->prStartLBA;//the hidden sectors
if(hidsec >= Capacity/512)hidsec = 0;
else
{
if(SD_ReadSingleBlock(pr->prStartLBA,fat_buffer))return 1;//read the bpb sector
bs = (bootsector710 *)fat_buffer;
if(bs->bsJump[0]!=0xE9 && bs->bsJump[0]!=0xEB)
{
hidsec = 0;
if(SD_ReadSingleBlock(0,fat_buffer))return 1;//read the bpb sector
bs = (bootsector710 *)fat_buffer;
}
}
if(bs->bsJump[0]!=0xE9 && bs->bsJump[0]!=0xEB)return 1;//对付没有bootsect的sd卡 //dead with the card which has no bootsect
bpb = (bpb710 *)bs->bsBPB;
if(bpb->bpbFATsecs)//detemine thd FAT type //do not support FAT12
{
FAT32_Enable=0; //FAT16
FATsectors = bpb->bpbFATsecs;//FAT表占用的扇区数
FirstDirClust = 2;
}
else
{
FAT32_Enable=1; //FAT32
FATsectors = bpb->bpbBigFATsecs;//FAT占用的扇区数 //the sectors number occupied by one fat talbe
FirstDirClust = bpb->bpbRootClust;
}
BytesPerSector = bpb->bpbBytesPerSec; //每扇区字节数
SectorsPerClust = (BYTE)bpb->bpbSecPerClust;//每簇扇区数
FirstFATSector = bpb->bpbResSectors+hidsec;//第一个FAT表扇区
RootDirCount = bpb->bpbRootDirEnts; //根目录项数
RootDirSectors = (RootDirCount*32)>>9; //根目录占用的扇区数
FirstDirSector = FirstFATSector+bpb->bpbFATs*FATsectors;//第一个目录扇区
FirstDataSector = FirstDirSector+RootDirSectors;//第一个数据扇区
return 0;
}
//读下一簇簇号
//Return the cluster number of next cluster of file
//Suitable for system which has limited RAM
unsigned long FAT_NextCluster(unsigned long cluster)
{
DWORD sector;
DWORD offset;
if(FAT32_Enable)offset = cluster/128;//FAT32的FAT表中,用四个字节表示一个粗地址.512/4=128
else offset = cluster/256; //FAT16的FAT表中,用两个字节表示一个粗地址.512/2=256
if(cluster<2)return 0x0ffffff8; //簇0,1不能用于存放
sector=FirstFATSector+offset;//计算实际扇区数
if(SD_ReadSingleBlock(sector,fat_buffer))return 0x0ffffff8;//读取FAT表,发生错误是返回0x0ffffff8
if(FAT32_Enable)
{
offset=cluster%128;//查找位置
sector=((unsigned long *)fat_buffer)[offset];
}
else
{
offset=cluster%256;//查找位置
sector=((unsigned short *)fat_buffer)[offset];
}
return (unsigned long)sector;//return the cluste number
}
//读下一簇簇号
//cluster:当前簇号
//startcluster:文件开始的簇号
//返回值:cluster前一个簇的簇号
//返回0xfffffff8则错误!
unsigned long FAT_PrevCluster(unsigned long cluster,unsigned long startcluster)
{
DWORD temp;
DWORD tempcluster;
tempcluster=startcluster;//从起始簇号开始查找
if(cluster==startcluster)return 0x0ffffff8;//查找错误
while(1)
{
temp=FAT_NextCluster(tempcluster); //查找当前簇的下一簇
if(temp==cluster)return tempcluster;//下一簇就等于最终簇,返回前一簇,就是最终簇的上一簇
else tempcluster=temp; //继续下一簇查找
if(temp==0x0ffffff8)return 0x0ffffff8;//查找错误
}
}
//将簇号转变为扇区号
u32 fatClustToSect(u32 cluster)
{
return FirstDataSector+(DWORD)(cluster-2)*(DWORD)SectorsPerClust;
}
//文件类型
//返回值:对应的类型 0,mp3;1,wma;2,wav,3,mid;4,lrc;5,txt;6,c;7,h;8,jpg;9,jpeg;10,bmp;11,file;12,FON;
const unsigned char *filetype[13]={"MP3","WMA","WAV","MID","LRC","TXT","C ","H ","JPG","JPE","BMP"," ","FON"};
//返回扩展名类型
//输入:exName 文件扩展名
u16 FileType_Tell(u8 * exName)
{
u8 i;
u8 t;
for(i=0;i<13;i++)
{
for(t=0;t<3;t++)if(exName[t]!=filetype[i][t])break;
if(t==3)break;
}
return 1<<i;//返回文件类型
}
//复制记录项信息
void CopyDirentruyItem(FileInfoStruct *Desti,direntry *Source)
{
BYTE i;
for(i=0;i<8;i++)Desti->F_ShortName[i]=Source->deName[i];//复制短文件名
Desti->F_Type = FileType_Tell(Source->deExtension);
Desti->F_StartCluster = Source->deStartCluster + (((unsigned long)Source->deHighClust)<<16);//不用管
Desti->F_Size = Source->deFileSize;
Desti->F_Attr = Source->deAttributes;
Desti->F_CurClust = 0;//扇区...
Desti->F_Offset = 0;//偏移0
//FAT的簇号不能是0(更目录簇号)
if(FAT32_Enable&&Desti->F_StartCluster==0)
{
Desti->F_StartCluster=FirstDirClust;//改变这个簇号.使其等于根目录所在簇号!!
}
if(LongNameFlag)//存在长文件名
{
LongNameBuffer[MAX_LONG_NAME_SIZE-1] = 0;
LongNameBuffer[MAX_LONG_NAME_SIZE-2] = 0;
UniToGB(LongNameBuffer); //把Unicode代码转换为ASICII码
for(i=0;i<80;i++)Desti->F_Name[i] = LongNameBuffer[i];//复制长文件名
}else //短文件名
{
if(Source->deName[0]==0x2e)//得到一个父目录(修改为:":\")
{
//保存父目录簇号
Fat_Dir_Cluster=Desti->F_StartCluster;
Desti->F_Name[0]=':';
Desti->F_Name[1]=0x5c;//'\'
Desti->F_Name[2]='\0';//加入结束符
}else //普通文件
{
for(i=0;i<11;i++)Desti->F_Name[i] = Source->deName[i];//复制短文件名
Desti->F_Name[11]='\0';//加入结束符
}
}
return ;
}
//浏览目标文件夹下面的一个文件类
//dir_clust:当前目录所在簇号
//FileInfo :目标文件的实体对象(FileInfoStruct体)
//type :要查找的文件类型:1<<0,mp3;1<<1,wma;1<<2,wav,1<<3,mid;1<<4,1<<lrc;
// 1<<5,txt;1<<6,jpg;1<<7,jpeg;1<<8,bmp;1<<9,file;
//count :0,返回当前目录下,该类型文件的个数;不为零时,返回第count个文件的详细信息
//返回值 :1,操作成功.0,操作失败
u8 Get_File_Info(u32 dir_clust,FileInfoStruct *FileInfo,u16 type,u16 *count)
{
DWORD sector;
DWORD cluster=dir_clust;
DWORD tempclust;
unsigned char cnt;
unsigned int offset;
unsigned short cont=0;//文件索引标志 <65536
unsigned char j; //long name fat_buffer offset;
unsigned char *p;//long name fat_buffer pointer
direntry *item = 0;
winentry *we =0;
cont=0;
LongNameFlag = 0;//清空长文件名标志
//SD_Init();//初始化SD卡,在意外拔出之后可以正常使用
//goto SD;
if(cluster==0 && FAT32_Enable==0)//FAT16根目录读取
{
for(cnt=0;cnt<RootDirSectors;cnt++)
{
if(SD_ReadSingleBlock(FirstDirSector+cnt,fat_buffer))return 1;//读数错误
//SD: for(offset=0;offset<512;offset++)fat_buffer[offset]=temp_buf[offset];
for(offset=0;offset<512;offset+=32)
{
item=(direntry *)(&fat_buffer[offset]);//指针转换
//找到一个可用的文件
if((item->deName[0]!=0x2E)&&(item->deName[0]!=0x00)&&(item->deName[0]!=0xe5)
||((item->deName[0]==0x2E)&&(item->deName[1]==0x2E)))//找到一个合法文件.忽略".",使用".."
{
if(item->deAttributes == 0x0f)//找到一个长文件名
{
we = (winentry *)(&fat_buffer[offset]);
j = 26 *( (we->weCnt-1) & WIN_CNT);//长文件名的长度
if(j<MAX_LONG_NAME_SIZE-25)
{
p = &LongNameBuffer[j];//偏移到目标地址
for (j=0;j<10;j++) *p++ = we->wePart1[j];
for (j=0;j<12;j++) *p++ = we->wePart2[j];
for (j=0;j<4;j++) *p++ = we->wePart3[j];
if (we->weCnt & 0x40) (*(unsigned int *)p) = 0;
if ((we->weCnt & WIN_CNT) == 1) LongNameFlag = 1;//最后一个长文件项找到了
}
}else
{
if(type&FileType_Tell(item->deExtension))//找到一个目标文件
{
cont++;//文件索引增加
}
//查找该目录下,type类型的文件个数
if(*count&&cont==*count)
{
//printf("\ncount:%d",*count);
CopyDirentruyItem(FileInfo,item);//复制目录项,提取详细信息
return 1;//找到目标文件成功
}
LongNameFlag=0;//清空长文件名
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -