📄 fat.c
字号:
//镇关西编写 QQ 191635418
#define fat_h
#include "fat.h"
extern unsigned char SD_Buffer[512];
extern UCHAR SD_Read_Block(ULONG addr);
extern void UDRT0_print(unsigned char d);
extern unsigned char getch();
void Debug_Pstr(const unsigned char *str);
void Debug_Pdata(unsigned long data);
void Debug_P16(unsigned char d);
void Debug_Msg(const unsigned char *str,unsigned long data);
unsigned long Block0_offset;
unsigned long FirstDataSector;
unsigned int BytesPerSector;
unsigned int SectorsPerCluster;
unsigned long FirstFATSector;
unsigned long FirstDirSector;
unsigned int FirstDirCluster; //Fat32时候根目录所在的簇
unsigned long FileSize;
unsigned long FatInCache = 0;
FOPT fopen_rcd[MAXFILES]; //用于记录被打开的文件的多少的
unsigned long FatSetBlock0()
{
//设置分区开始的偏移量
//逻辑扇区0 相对于物理扇区0的偏移量
Block0_offset=*((ULONG*)(&SD_Buffer[0x1c6]));
return Block0_offset;
}
/*
unsigned char FatReadBlock(ULONG addr)
{
return SD_Read_Block(Block0_offset+addr);
}
*/
#define FatReadBlock(addr) SD_Read_Block(Block0_offset+addr)
unsigned long ClustToSector(unsigned long Clust)
{
return (Clust-2)*SectorsPerCluster+FirstDataSector;
}
unsigned long FindNextClust(unsigned long NowClust)
{
unsigned int offset;
//unsigned long ret;
NowClust<<=2;
offset=NowClust%BytesPerSector;
NowClust/=BytesPerSector;
FatReadBlock(NowClust+FirstFATSector);
//Debug_Msg("偏移:",offset);
//Debug_Msg("扇区:",NowClust);
//Debug_Msg("扇区数据:",SD_Buffer[offset]);
//ret=*( (unsigned long*)(&SD_Buffer[offset]) ); //可能要考虑大端小端的问题 在不同的编译器中
//return ret;
return *( (unsigned long*)(&SD_Buffer[offset]) );
}
void InitFat32()
{
struct bpb710 *bpb;
SD_Read_Block(0);
FatSetBlock0();
FatReadBlock(0); //读取逻辑扇区0 系统引导区
//Debug_Msg("逻辑0扇区地址:",Block0_offset);
bpb=(struct bpb710 *)(&SD_Buffer[0x0B]); //获取相关信息
BytesPerSector=bpb->bpbBytesPerSec;
//Debug_Msg("每个扇区的字节数",BytesPerSector);
SectorsPerCluster=bpb->bpbSecPerClust;
//Debug_Msg("每个簇的扇区数",SectorsPerCluster);
FirstDataSector=bpb->bpbResSectors+bpb->bpbFATs*bpb->bpbBigFATsecs;
//Debug_Msg("数据区的开始位置:",FirstDataSector);
FirstFATSector= bpb->bpbResSectors;
//Debug_Msg("FAT表格大小",bpb->bpbBigFATsecs);
//Debug_Msg("Fat表格的开始位置:",FirstFATSector);
FirstDirCluster=bpb->bpbRootClust;
//Debug_Msg("根目录所在簇:",FirstDirCluster);
FirstDirSector=bpb->bpbResSectors+bpb->bpbFATs*bpb->bpbBigFATsecs;
//FatReadBlock(FirstFATSector);
//FatReadBlock(FirstDataSector);
/*
{
unsigned int i;
for(i=0;i<512;i++)
{
if(((i&0x0f)==0)) {UDRT0_print('\n');UDRT0_print('\r');}
Debug_P16(SD_Buffer[i]);
}
}
*/
}
unsigned char Cmpstr_withnum(unsigned char *d1,unsigned char *d2,unsigned char len)
{
while(len--)
{
if(*d1++!=*d2++) return 0;
}
return 1;
}
unsigned char GetFileName(unsigned char *filename,const unsigned char **instr )
{
unsigned char i,d;
for(i=0;i<11;i++) filename[i]=0x20;
while(**instr=='/') (*instr)++;
i=0;d=**instr;
while(d!=0 && d!='.' && d!='/' && i<8)
{
if(d>='a' && d<='z') filename[i]=d+'A'-'a';
else filename[i]=d;
++i;
++(*instr);
d=**instr;
}
if(d!=0 && d!='/')
{
if(d!='.') return 0; //文件名字大于8个字节 错误
++(*instr);
i=0;d=**instr;
while(d!=0 && d!='/' && i<3)
{
if(d>='a' && d<='z') filename[i+8]=d+'A'-'a';
else filename[i+8]=d;
++i;
++(*instr);
d=**instr;
}
}
return 1;
}
unsigned long GetFileInf(unsigned char *filename,unsigned long curclust)
{
unsigned int FileCnt,SectorsCnt;
unsigned long CurSetor;
while(curclust<0xFFFFFF0F){
CurSetor=ClustToSector(curclust);
for(SectorsCnt=0;SectorsCnt<SectorsPerCluster;SectorsCnt++)
{
FatReadBlock(CurSetor);
for(FileCnt=0;FileCnt<BytesPerSector;FileCnt+=32)
{
if(Cmpstr_withnum(&SD_Buffer[FileCnt],filename,11))
return FileCnt/32+CurSetor*16; //返回文件名字在那个扇区的第几个文件项
}
++CurSetor;
}
curclust=FindNextClust(curclust);
}
return 0;
}
unsigned char fopen( const unsigned char *file) //只针对根目录
{
unsigned char i;
unsigned char file_number;
unsigned char filename[11];
unsigned long curclust;
unsigned long fileinfat;
FFS *fatfilestruct;
for(file_number=0;file_number<sizeof(fopen_rcd)/sizeof(fopen_rcd[0]);i++)
{
if(fopen_rcd[file_number].StartClust==0) break;
}
if(file_number>=sizeof(fopen_rcd)/sizeof(fopen_rcd[0])) return 0;
curclust=FirstDirCluster;
while(1){
if(!GetFileName(filename,&file)) return 0;
//Debug_Pstr("\n\r");
//for(i=0;i<11;i++) UDRT0_print(filename[i]);
//Debug_Pstr("\n\r");
fileinfat=GetFileInf(filename,curclust);
if(!fileinfat) return 0; //can't find the file
fatfilestruct=(FFS*)(&SD_Buffer[ (fileinfat&0x0f)*32]);
curclust=fatfilestruct->StartHight;
curclust<<=16;
curclust+=fatfilestruct->StartLow;
//Debug_Msg("文件所在簇:",curclust);
if(*file==0) break;
}
fopen_rcd[file_number].StartClust=curclust; //set used mark of fopen_rcd[file_number]
fopen_rcd[file_number].FatPos=fileinfat; //记录文件在fat表格位置,为删除 修改文件做准备
fopen_rcd[file_number].Seek=0;
fopen_rcd[file_number].CurClust=curclust;
fopen_rcd[file_number].CurSector=ClustToSector(curclust);
fopen_rcd[file_number].Size=fatfilestruct->Size;
return file_number;
}
unsigned char fread(void *save,unsigned long len,unsigned char file_number)
{
unsigned int block_len,blockoffset,i;
unsigned char *buf=(unsigned char *)save;
if(len+fopen_rcd[file_number].Seek>fopen_rcd[file_number].Size)
if(fopen_rcd[file_number].Seek>=fopen_rcd[file_number].Size) return 0;
blockoffset=fopen_rcd[file_number].Seek%BytesPerSector;
block_len=BytesPerSector-blockoffset;
if(block_len>len) block_len=len;
while(len)
{
FatReadBlock(fopen_rcd[file_number].CurSector); //读取当前块
for(i=0;i<block_len;i++) {
*buf++=SD_Buffer[blockoffset+i];
}
fopen_rcd[file_number].Seek+=block_len;
if(fopen_rcd[file_number].Seek%BytesPerSector==0)
{
if( (fopen_rcd[file_number].Seek/BytesPerSector)%SectorsPerCluster ==0 )
{
fopen_rcd[file_number].CurClust=FindNextClust(fopen_rcd[file_number].CurClust);
fopen_rcd[file_number].CurSector=ClustToSector(fopen_rcd[file_number].CurClust);
}
else ++fopen_rcd[file_number].CurSector;
}
len=len-block_len;
if(len>BytesPerSector) block_len=BytesPerSector;
else block_len=len;
blockoffset=0;
}
return 1;
}
unsigned char fseek(unsigned char file_number,unsigned long addr,unsigned char type) //文件定位 主要设置 clust sector and seek
{
unsigned long TempCnt;
if(fopen_rcd[file_number].StartClust==0) return 0; //no files
if(type==0) //绝对地址
{
if(addr>=fopen_rcd[file_number].Size) return 0;
fopen_rcd[file_number].CurClust=fopen_rcd[file_number].StartClust;
fopen_rcd[file_number].Seek=addr;
TempCnt=fopen_rcd[file_number].Seek/SectorsPerCluster/BytesPerSector;
}else if(type==1) //相对地址
{
TempCnt=(fopen_rcd[file_number].Seek%(SectorsPerCluster*BytesPerSector)+addr)
/SectorsPerCluster/BytesPerSector;
addr+=fopen_rcd[file_number].Seek;
if(addr>=fopen_rcd[file_number].Size) return 0;
fopen_rcd[file_number].Seek=addr;
}
while(TempCnt--){
fopen_rcd[file_number].CurClust=FindNextClust(fopen_rcd[file_number].CurClust);
}
TempCnt=(fopen_rcd[file_number].Seek/BytesPerSector)%SectorsPerCluster;
fopen_rcd[file_number].CurSector=ClustToSector(fopen_rcd[file_number].CurClust);
fopen_rcd[file_number].CurSector+=TempCnt;
return 1;
}
unsigned long ftell(unsigned char file_number)
{
if(fopen_rcd[file_number].StartClust==0) return 0xFFFFFFFF; //error
else return fopen_rcd[file_number].Seek; //读写指针位置
}
unsigned char fclose(unsigned char file_number)
{
if(fopen_rcd[file_number].StartClust==0) return 0;
fopen_rcd[file_number].StartClust=0;
return 1;
}
void fprtfile(unsigned char file_number)
{
Debug_Msg("文件指针所在的簇",fopen_rcd[file_number].CurClust);
Debug_Msg("文件指针所在的扇区",fopen_rcd[file_number].CurSector);
Debug_Msg("文件指针的大小",fopen_rcd[file_number].Seek);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -