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

📄 fat.c

📁 基于stm32的MP3播放器
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -