⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 SD卡的读写
💻 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 + -