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

📄 fat.c

📁 STM32不完全手册 例程源码 29个
💻 C
📖 第 1 页 / 共 2 页
字号:
#include"FAT.h"
#include "usart.h"
//////////////////////////////////////////////////////////////////////////////////	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//Mini STM32开发板
//FAT 驱动代码		   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2010/5/13 
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 正点原子 2009-2019
//All rights reserved
//////////////////////////////////////////////////////////////////////////////////	 
 

//全局变量区域
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文件系统标志
	    
DWORD Cur_Dir_Cluster;//当前目录簇号
//DWORD Fat_Dir_Cluster;//父目录簇号 在FAT文件夹里面CopyDirentruyItem函数中修改!
	
FAT_TABLE FAT_TAB;//TINY FAT表		 

//文件信息缓存区		   		    															   
FileInfoStruct F_Info[3];
//外部全局变量

//FAT 数据缓存区
u8 fat_buffer[512];//用于存储FAT数据
u8 LongNameBuffer[MAX_LONG_NAME_SIZE];//长文件名的缓存区
BOOL LongNameFlag = 0;//是否存在长文件名的标志


//文件类型
//3gp,3g2,m4a,mp4也是支持的.
//返回值:对应的类型   
//0,mp1;1,mp2;2,mp3;3,mp4;4,m4a;5,3gp;6,3g2;7,ogg;8,acc;9,wma;10,wav;11,midi;12,flac;
//13,lrc;14,txt;15,c;16,h;17,file;18,FON;19,SYS;20,bmp;21,jpg;22,jpeg;   
const unsigned char *filetype[23]=
{
"MP1","MP2","MP3","MP4","M4A","3GP","3G2","OGG","ACC","WMA","WAV","MID","FLA",
"LRC","TXT","C  ","H  ","   ","FON","SYS","BMP","JPG","JPE"
};
//返回扩展名类型
//输入:exName 文件扩展名
//返回值:文件的类型,目前支持20种文件类型,最大支持32种文件类型
u32 FileType_Tell(u8 * exName)
{
    u8 i;
    u8 t;   
    for(i=0;i<20;i++)
    { 
        for(t=0;t<3;t++)if(exName[t]!=filetype[i][t])break; 
        if(t==3)break;
    } 
    return 1<<i;//返回文件类型
}  
//FAT初始化,不含SD的初始化,用之前应先调用sd的初始化
//返回值:0,初始化成功
//    其他,初始化失败   
unsigned char FAT_Init(void)//Initialize of FAT  need initialize SD first
{  		   
	bootsector710 *bs  = 0;
	bpb710        *bpb = 0;			  
	partrecord    *pr  = 0;

	DWORD hidsec=0;
	u32 Capacity;	 
	Capacity = SD_GetCapacity();				   
	if(Capacity<0xff)return 1;	    
	if(SD_ReadSingleBlock(0,fat_buffer))return 2;
	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 3;//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 4;//read the bpb sector
			bs = (bootsector710 *)fat_buffer;	
		}
	}	  
	if(bs->bsJump[0]!=0xE9 && bs->bsJump[0]!=0xEB)return 5;//对付没有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占用的扇区数 
		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; 
}  
//将FAT表,从头到尾COPY过来,如果没COPY完,则Fat_Over=0,否则为1   
//cluster:文件的首簇
void Copy_Fat_Table(unsigned long cluster)
{
	u32 bcluster; 
	u8 fat_base;//0~Fat_Table_Size	 
	FAT_TAB.Fat_Over=0;	   
    for(fat_base=0;fat_base<Fat_Table_Size;fat_base++)
	{
		FAT_TAB.Fat_Base_Tab[fat_base]=0;
		FAT_TAB.Fat_Base_Len[fat_base]=0;//全部清空
	}
	fat_base=0;
	bcluster=cluster;//起始簇,不能丢失的.
	FAT_TAB.Fat_Base_Tab[fat_base]=bcluster;
	FAT_TAB.Fat_Base_Len[fat_base]=1;//有1个数据了,就是最新的bcluster	  
	while(1)
	{
	    bcluster=FAT_NextCluster(bcluster);	   
		if((FAT32_Enable==0&&bcluster==0xffff)||bcluster==0x0ffffff8||bcluster==0x0fffffff)//文件结束 
		{
			FAT_TAB.Fat_Over=1;//文件COPY结束
			break; 
		} 	 		
		if(bcluster-FAT_TAB.Fat_Base_Tab[fat_base]-FAT_TAB.Fat_Base_Len[fat_base]!=0)//是否满足偏移条件
		{
			fat_base++;//启用下一个BASE
			if(fat_base>=Fat_Table_Size)//超出了缓冲区范围,文件太大了/磁盘太零散了!!!
			{
				FAT_TAB.Fat_Over=0;//文件COPY结束
				break; 
			}
			FAT_TAB.Fat_Base_Tab[fat_base]=bcluster;
			FAT_TAB.Fat_Base_Len[fat_base]=1;//有1个数据了,就是最新的bcluster				
		}else FAT_TAB.Fat_Base_Len[fat_base]++;//基址偏移量增加	   
	}
	//监控用
	//printf("Fat_Over:%d\n",FAT_TAB.Fat_Over);
	//printf("Fat_Head_Pos:%d\n",FAT_TAB.Fat_Head_Pos);
	//printf("Fat_Base_Tab[0]:%d\n",FAT_TAB.Fat_Base_Tab[0]);
	//printf("Fat_Base_Tab[1]:%d\n",FAT_TAB.Fat_Base_Tab[1]);
	//printf("Fat_Base_Tab[2]:%d\n",FAT_TAB.Fat_Base_Tab[2]);		 
}	    							    
//在TINY FAT表里面查找cluster的上一个簇号
//cluster:当前簇号
//返回值:cluster,表示不能再向上了
//	      其他值,cluster的上一个簇	   
u32 FatTab_Prev_Cluster(unsigned long cluster)
{
	u8 t;	 
	u32 tempclust;
RSTP:
	for(t=0;t<Fat_Table_Size;t++)
	{
		if(cluster<=(FAT_TAB.Fat_Base_Tab[t]+FAT_TAB.Fat_Base_Len[t]-1)&&cluster>=FAT_TAB.Fat_Base_Tab[t])break;//在这个BASE内
	}	  
	if(cluster==FAT_TAB.Fat_Base_Tab[t])//是在BASE,但是是第一个
	{		 
		if(t==0)//这份FAT表 全部找完还没找到
		{					 									    
			if(FAT_TAB.Fat_Head_Pos>0)//不超过范围
			{
				FAT_TAB.Fat_Head_Pos--;
				tempclust=FAT_TAB.Fat_Base_Head[FAT_TAB.Fat_Head_Pos];//拷贝上一个tinyFAT表的表头
			}else return cluster;   //无法继续向上
			Copy_Fat_Table(tempclust);//COPY 上一个tinyFAT表
			goto RSTP;
			//return FAT_TAB.Fat_Base_Tab[Fat_Table_Size-1]+FAT_TAB.Fat_Base_Len[Fat_Table_Size-1]-1;//返回上一个簇号		 
		} 																 
		return FAT_TAB.Fat_Base_Tab[t-1]+FAT_TAB.Fat_Base_Len[t-1]-1;//上一个簇号
	}else return --cluster;//返回上一个簇   
}	 
//在TINY FAT表里面查找cluster的下一个簇号
//cluster:当前簇号
//返回值:0x0ffffff8,表示没有后续簇了
//	   		 其他值,对应簇号
u32 FatTab_Next_Cluster(unsigned long cluster)
{
	u8 t;	 
RESN:
	for(t=0;t<Fat_Table_Size;t++)
	{
		if(cluster<=(FAT_TAB.Fat_Base_Tab[t]+FAT_TAB.Fat_Base_Len[t]-1)&&cluster>=FAT_TAB.Fat_Base_Tab[t])break;//在这个BASE内
	}	  
	if(cluster==FAT_TAB.Fat_Base_Tab[t]+FAT_TAB.Fat_Base_Len[t]-1)//是在BASE,但是是最后一个了
	{		 
		if((t+1)==Fat_Table_Size)//全部找完还没找到
		{														  
			if(FAT_TAB.Fat_Over)return 0x0ffffff8;//文件结束了	 
			if(FAT_TAB.Fat_Head_Pos<Fat_Head_Size-1)//不超过范围
			{		  
				FAT_TAB.Fat_Base_Head[FAT_TAB.Fat_Head_Pos]=FAT_TAB.Fat_Base_Tab[0];//拷贝当前tinyFAT表的第一个簇
				FAT_TAB.Fat_Head_Pos++;
			}
			Copy_Fat_Table(cluster);//COPY 余下的FAT表
			goto RESN;
		} 
		if(FAT_TAB.Fat_Base_Len[t+1]==0)return 0x0ffffff8;//没有后续簇了
		return FAT_TAB.Fat_Base_Tab[t+1];//下一个簇号
	}else return ++cluster;//返回下一个簇   
}	  
//在SD卡上的FAT表中查找下一簇号
//cluster:当前簇号
//返回值:0x0ffffff8,表示没有后续簇了
//	   		 其他值,下一簇号				   		    
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];//u32	
	}
	else
	{
		offset=cluster%256;//计算在扇区内的偏移
		sector=((unsigned short *)fat_buffer)[offset];//u16
	}			   
	return (unsigned long)sector;//return the cluste number
}	  
//将簇号转变为扇区号
//cluster:要变为扇区的簇号
//返回值:cluster对应的扇区号
u32 fatClustToSect(u32 cluster)
{
	return FirstDataSector+(DWORD)(cluster-2)*(DWORD)SectorsPerClust;	 
}	 
//复制记录项信息
//将Source的相关内容复制到Desti里面
void CopyDirentruyItem(FileInfoStruct *Desti,direntry *Source)
{
	u8 i;
	u8 t;
	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 //短文件名
	{	//2E:当前目录所在簇.2E 2E:父目录所在簇.
		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	    			  //普通文件

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -