fat32.c

来自「用MEGA16驱动SD卡」· C语言 代码 · 共 281 行

C
281
字号
#include <mega16.h>       
#include "SD.c"         
/*----------------------数据类型定义-----------------------*/
#define uint8 unsigned char  //8位无符号整数
#define uint16 unsigned int  //16位无符号整数      
#define uint32 unsigned long int //32位无符号整数    
#define FIND_UP_RANGE 128  
//定义根目录下最大的文件名描述项
//根目录占据一个簇的大小,每个目录或者文件用32个字节描述
//所以目录加文件的描述项一般就是128个
//8*512/32=128 
uint8 BUFF[512];
uint8 table[10]={'0','1','2','3','4','5','6','7','8','9'}; 
/*----------------记录FAT表中簇项-----------*/
//每四个字节一个簇项
//一个扇区中有128个簇项  128=512/4
struct FAT32_FAT_Item
{
 uint8 Item[4];
};

struct FAT32_FAT
{
 struct FAT32_FAT_Item Items[128];
};

/*----FAT32中对BPB的定义如下  一共占用90个字节--*/
struct FAT32_BPB
{
 uint8 BS_jmpBoot[3];     //跳转指令            offset: 0
 uint8 BS_OEMName[8];     //                    offset: 3
 uint8 BPB_BytesPerSec[2];//每扇区字节数        offset:11
 uint8 BPB_SecPerClus[1]; //每簇扇区数          offset:13
 uint8 BPB_RsvdSecCnt[2]; //保留扇区数目        offset:14
 uint8 BPB_NumFATs[1];    //此卷中FAT表数       offset:16
 uint8 BPB_RootEntCnt[2]; //FAT32为0            offset:17
 uint8 BPB_TotSec16[2];   //FAT32为0            offset:19
 uint8 BPB_Media[1];      //存储介质            offset:21
 uint8 BPB_FATSz16[2];    //FAT32为0            offset:22
 uint8 BPB_SecPerTrk[2];  //磁道扇区数          offset:24
 uint8 BPB_NumHeads[2];   //磁头数              offset:26
 uint8 BPB_HiddSec[4];    //FAT区前隐扇区数     offset:28
 uint8 BPB_TotSec32[4];   //该卷总扇区数        offset:32
 uint8 BPB_FATSz32[4];    //一个FAT表扇区数     offset:36
 uint8 BPB_ExtFlags[2];   //FAT32特有           offset:40
 uint8 BPB_FSVer[2];      //FAT32特有           offset:42
 uint8 BPB_RootClus[4];   //根目录簇号          offset:44
 uint8 FSInfo[2];         //保留扇区FSINFO扇区数offset:48
 uint8 BPB_BkBootSec[2];  //通常为6             offset:50
 uint8 BPB_Reserved[12];  //扩展用              offset:52
 uint8 BS_DrvNum[1];      //                    offset:64
 uint8 BS_Reserved1[1];   //                    offset:65
 uint8 BS_BootSig[1];     //                    offset:66
 uint8 BS_VolID[4];       //                    offset:67
 uint8 BS_FilSysType[11]; //	                offset:71
 uint8 BS_FilSysType1[8]; //"FAT32    "         offset:82
};

struct FAT32_INI_ARG//FAT32初始化基本信息
{
	uint16 BytesPerSec;//一个扇区的字节数
	uint8  SecPerClus;//一个簇的扇区数
	uint16 RsvdSecCnt;//保留扇区数
	uint8  NumFATs;//FAT表的数目
	uint32 FATSz32; //FAT表的扇区数 
	uint32 FirstFatAddr;//第一个FAT表地址
	uint32 RootDirAddr;//根目录地址----也是第二簇的地址
	
}Fat_Info;   

/*--------------------------目录或文件定义---------------------*/
struct direntry 
{
 uint8 deName[8];       // 文件名
 uint8 deExtension[3]; 	// 扩展名
 uint8 deAttributes;   	// 文件属性
 uint8 deLowerCase;    	// 系统保留
 uint8 deCHundredth;   	// 创建时间的10 毫秒位
 uint8 deCTime[2];     	// 文件创建时间
 uint8 deCDate[2];     	// 文件创建日期
 uint8 deADate[2];     	// 文件最后访问日期
 uint8 deHighClust[2];  // 文件起始簇号的高16 位
 uint8 deMTime[2];     	// 文件的最近修改时间
 uint8 deMDate[2];     	// 文件的最近修改日期
 uint8 deLowCluster[2];// 文件起始簇号的低16 位
 uint8 deFileSize[4];   // 表示文件的长度
};

/*-----------------------被读取文件的信息-----------------*/
struct File_Arg
{
 uint8   FileName[12];	//文件名 包括扩展名前的	    " . "
 uint32  FileStartCluster;	//文件首簇号
 uint32  FileCurCluster;	//文件当前簇号
 uint32  FileNextCluster;	//下一簇号
 uint32  FileSize;	//文件大小 
 uint8   FileAttr;	//文件属性
 uint8   FileCreateTime;	//文件建立时间
 uint8   FileCreateDate;	//文件建立日期
 uint8   FileMTime;	//文件修改时间
 uint8   FileMDate;	//文件修改日期
 uint32  FileSector;	//文件当前扇区
 uint16  FileOffset;	//文件偏移量
}File_Info;


uint32 lb2bb(uint8 *dat,uint8 len) //小端转为大端
{
 	uint32 temp=0;
 	uint32 fact=1;
 	uint32 i=0;
 	for(i=0;i<len;i++)//一个字节对应256
 	{
  		temp+=dat[i]*fact;
  		fact*=256;
 	}
 	return temp;
}   

uint8 INI_FAT32()//FAT32的初始化函数
{ 
        struct FAT32_BPB *p; 
       	Rbyte_SD(BUFF,0,512);//读出BPB的信息并放在缓冲区间中
	p=(struct FAT32_BPB *)BUFF;//转换指针
	Fat_Info.BytesPerSec=(uint16)lb2bb((*p)->BPB_BytesPerSec,2); 
	Fat_Info.SecPerClus=(*p)->BPB_SecPerClus[0];
	Fat_Info.RsvdSecCnt=lb2bb((*p)->BPB_RsvdSecCnt,2);  
	Fat_Info.NumFATs=(*p)->BPB_NumFATs[0]; 
	Fat_Info.FATSz32=lb2bb((*p)->BPB_FATSz32,4);
	//第一个FAT表头的地址 = 扇区字节数 x 保留区数
	Fat_Info.FirstFatAddr=Fat_Info.BytesPerSec*Fat_Info.RsvdSecCnt;
	//根目录地址 = 第一个FAT表头地址 + 两个FAT表长
	Fat_Info.RootDirAddr=Fat_Info.FirstFatAddr+Fat_Info.FATSz32*Fat_Info.NumFATs*Fat_Info.BytesPerSec;
	/*测试初始化的语句
		Rbyte_SD(BUFF,Fat_Info.RootDirAddr,512);
       		lcd_wdat(table[Fat_Info.BytesPerSec/100]);
		lcd_wdat(table[Fat_Info.BytesPerSec/10%10]);
		lcd_wdat(table[Fat_Info.BytesPerSec%10]); 
		lcd_wdat(table[Fat_Info.SecPerClus]);
		lcd_wdat(table[Fat_Info.RsvdSecCnt/10]);
		lcd_wdat(table[Fat_Info.RsvdSecCnt%10]);
		lcd_wdat(table[Fat_Info.NumFATs]);
		lcd_wdat(table[Fat_Info.FATSz32/1000]);
		lcd_wdat(table[Fat_Info.FATSz32/100%10]);
		lcd_wdat(table[Fat_Info.FATSz32/10%10]);
		lcd_wdat(table[Fat_Info.FATSz32%10]);   
		lcd_wdat(BUFF[0]);
		lcd_wdat(BUFF[1]);
	*/
} 

uint8 Compare_File_Name(uint8 *p1,uint8 *p2)
{
	//判断文件名是否相等(包括扩展名)
	uint8 i,j=8;
 	uint8 name_temp[12];//用来将输入的文件名转换为标准的文件名
 	for(i=0;i<11;i++) 
 		name_temp[i]=0x20;//全部输入空格
 	name_temp[11]=0;//文件属性位为只读
 	i=0;
 	while(*p1!='.')
       {
  		name_temp[i++]=*p1++;
  	}
	 i++;
	 p1++;
 	while(*p1!=0)
       {
  		name_temp[j++]=*p1++;
 	}
 	for(i=0;i<11;i++)
 	{
  		if(name_temp[i]!=*p2++) 
  			return 0;
 	}
   	return 1;
}  

struct direntry  *Find_File(uint8 *File_Name)
{
	struct direntry *p;  
	uint8 retry=0;
	uint8 i;
	Rbyte_SD(BUFF,Fat_Info.RootDirAddr,512);//读取根目录的第一个扇区   
	p=(struct direntry *)BUFF; 
	while(retry<FIND_UP_RANGE)
	{
		if((*p)->deName[0]!=0xE5&&(*p)->deName[0]!=0x00&&(*p)->deName[0]!=0x0f)
		//判断是否有意义
		{
			if(Compare_File_Name(File_Name,(*p)->deName)==1)
				return p;
		}   
		p++;
		retry++;
	}   
	//如果没有找到文件,返回0指针                    
	return 0;
} 

uint32 Get_NextCluster(uint32  FileCurCluster)
{
	uint32 temp;
 	temp=((FileCurCluster/128)*512+Fat_Info.FirstFatAddr);
 	Rbyte_SD(BUFF,temp,512); 
	return lb2bb(&BUFF[FileCurCluster*4],4);

}

void File_Print()//把数据发送到显示终端上
{;}

uint8 READ_FILE(uint8 *File_Name)
{                          
	uint8 i=0; 
	uint32 sub;//记录该文件还要多少数据没有读出 
	uint32 iSectorInCluster=0;//记录读取了一个簇中的扇区数
	struct direntry *p;
	if((p=Find_File(File_Name))==0)
	{
		return 0;
	} 
	//---------开始初始化文件信息 
	for(i=0;i<=7;i++)//文件名
	{
		File_Info.FileName[i]=(*p)->deName[i];
	}
	File_Info.FileName[i]='.';
	for(i=0;i<=2;i++)//扩展名  
	{
		File_Info.FileName[i]=(*p)->deExtension[i];
	}
	//文件属性
	File_Info.FileAttr=(*p)->deAttributes;
	//首簇号
	File_Info.FileStartCluster=(lb2bb((*p)->deHighClust,2)<<16)+lb2bb((*p)->deLowCluster,2);  
	lcd_wdat(table[File_Info.FileStartCluster]);
       //测试用的 Rbyte_SD(BUFF,Fat_Info.RootDirAddr+(File_Info.FileStartCluster-0x00000002)*8*512,512);
        //当前簇号
        File_Info.FileCurCluster=File_Info.FileStartCluster;
        //文件大小  
        File_Info.FileSize=lb2bb((*p)->deFileSize,4);
        //文件偏离量
        File_Info.FileOffset=0;
        sub=File_Info.FileSize - File_Info.FileOffset;
        //下一簇号
        File_Info.FileNextCluster=Get_NextCluster(File_Info.FileCurCluster);   
        //开始读取文件  
  	lcd_wdat(table[File_Info.FileNextCluster]);
        lcd_wdat('V'); 
        while(File_Info.FileNextCluster!=0x0fffffff)
       {        
       		lcd_wdat(table[Fat_Info.SecPerClus]); 
       		for(iSectorInCluster=0;iSectorInCluster<Fat_Info.SecPerClus;iSectorInCluster++)//读出整簇数据
       		{
         		Rbyte_SD(BUFF,Fat_Info.RootDirAddr+(File_Info.FileCurCluster-0x00000002+iSectorInCluster)*8*512,512);
         		File_Print();  
         		File_Info.FileOffset=File_Info.FileOffset+512;
         	}
         	lcd_wdat(table[iSectorInCluster]); 
         	//Fat簇链传递
         	File_Info.FileCurCluster=File_Info.FileNextCluster;
         	File_Info.FileNextCluster=Get_NextCluster(File_Info.FileCurCluster);
         	//文件偏移量的处理
         	sub=File_Info.FileSize-File_Info.FileOffset;
        }     
        
        iSectorInCluster=0;
        while(sub>=Fat_Info.BytesPerSec)//读出不满一个簇的数据
        {
        	Rbyte_SD(BUFF,Fat_Info.RootDirAddr+(File_Info.FileCurCluster-2+iSectorInCluster)*8*512,512);
        	File_Print();   
        	File_Info.FileOffset=File_Info.FileOffset+512;
        	sub=File_Info.FileSize - File_Info.FileOffset;
        	iSectorInCluster++;
        }       
        Rbyte_SD(BUFF,Fat_Info.RootDirAddr+(File_Info.FileCurCluster-2+iSectorInCluster)*8*512,512);
 }
	 
	

⌨️ 快捷键说明

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