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

📄 fat16.c

📁 SD和FAT文件系统.rar
💻 C
字号:
#include "datatype.h"
#include "fat16.h"
INT8U g_u8Fat16Buf[512];

FAT16_INIT_ARG g_Fat16InitArg;
FILE_INFO g_FileInfo;
/*************************************************************************
*名称: ByteUnite
*功能: 多字节合并
*参数: 无
*返回: 合并后的数据
*************************************************************************/
INT32U ByteUnite(INT8U *pu8Data, INT8U u8Len)
{
	INT32U temp = 0; 
	INT32U u32Fact = 1; 
	INT8U i=0; 
	for(i = 0; i < u8Len; i++) 
	{ 
		temp += pu8Data[i] * u32Fact; 
		u32Fact <<= 8; 
	} 
	return temp;
}
INT8U FAT16_ReadSec(INT32U u32SecNo, INT8U *pu8Buf)
{
	INT8U temp;
	temp = SD_ReadBlockSingle(u32SecNo, pu8Buf);
	return temp;
}

/*************************************************************************
*名称: FAT16_FindBPB
*功能: 寻找BPB所在的扇区号
*参数: 无
*返回: BPB所在的扇区号
*************************************************************************/
INT32U  FAT16_FindBPB(void)  
{
	INT32U u32BpbSectNo = 0;
	while(u32BpbSectNo < FIND_BPB_UP_RANGE)
	{ 
		SD_ReadBlockSingle(u32BpbSectNo,g_u8Fat16Buf);
		if(g_u8Fat16Buf[0] == 0xEB && g_u8Fat16Buf[2] == 0x90)
		{
			break;
		}
		u32BpbSectNo++;
	}
	return u32BpbSectNo;
}

/*************************************************************************
*名称: FAT16_Init
*功能: FAT16文件系统初始化
*参数: pArg文件系统参数指针
*返回: 零成功非零失败
*************************************************************************/
INT8U FAT16_Init(PFAT16_INIT_ARG pArg) 
{ 
	INT32U temp;
	PFAT16_BPB bpb=(PFAT16_BPB)(g_u8Fat16Buf);             
	//将数据缓冲区指针转为 struct FAT32_BPB  型指针 
	pArg->BPBSecNo = FAT16_FindBPB();  
	pArg->TotSize = g_SDInfo.cap; //获取分区容量 
	//计算FAT表占用的扇区数 
	if(ByteUnite(bpb->BPB_FATSz16, 2) != 0) 
	{
		pArg->FATSz = ByteUnite(bpb->BPB_FATSz16, 2); 
	}
	else
	{                
		pArg->FATSz = ByteUnite(bpb->BPB_FATSz32, 4);                  
	}	
	//计算总的扇区数
  if (ByteUnite(bpb->BPB_TotSec16, 2)!= 0) 
  { 
      pArg->TotSec = ByteUnite(bpb->BPB_TotSec16, 2); 
  } 
  else 
  { 
      pArg->TotSec  = ByteUnite(bpb->BPB_TotSec32, 4); 
  }     
      
	pArg->FirstDirClus = ByteUnite(bpb->BPB_RootClus, 4);                  
	//计算根目录簇号
	pArg->BytesPerSec = ByteUnite(bpb->BPB_BytesPerSec, 2);                  
	//计算每扇区字节数 
	pArg->SecPerClus = bpb->BPB_SecPerClus[0];                  
	//计算每簇扇区数
	pArg->FirstFATSec = ByteUnite(bpb->BPB_RsvdSecCnt,2) 
									+ pArg->BPBSecNo; 
	//计算第一个 FAT 表扇区号
	pArg->RootDirCount = ByteUnite(bpb->BPB_RootEntCnt, 2);                  
	//计算根目录项数
	pArg->RootDirSz = (pArg->RootDirCount)*32 >> 9;                  
	//装计算根目录占用的扇区数
	//pArg->FirstDirSec = (INT32U)(pArg->FATSz);
	pArg->FirstDirSec  = pArg->FirstFATSec + bpb->BPB_NumFATs[0] 
											* pArg->FATSz;  
	//计算第一个目录扇区到 
	pArg->FirstDataSec =(pArg->FirstDirSec)+(pArg->RootDirSz);  
	//计算第一个数据扇区到 
	pArg->DataSec =  pArg->TotSec - (ByteUnite(bpb->BPB_RsvdSecCnt,2) 
	            	+ (bpb->BPB_NumFATs[0]* pArg->FATSz) 
	            	+ pArg->RootDirSz);
	pArg->ClusCnt= pArg->DataSec / bpb->BPB_SecPerClus[0]; //计算簇数
	//判断文件类型
	if(pArg->ClusCnt < 4085)
	{
		pArg->FATType = FAT_TYPE_FAT12;
	}
	else if(pArg->ClusCnt < 65525) 
	{
		pArg->FATType = FAT_TYPE_FAT16;
	}
	else
	{
		pArg->FATType = FAT_TYPE_FAT32;
	}           	
	return 0;
}
INT32U FAT16_GetNextClus(INT32U u32CurClus) 
{ 
	INT32U temp; 
	temp =((u32CurClus / 256) + g_Fat16InitArg.FirstFATSec);    
	//计算给定簇号对应的簇项的扇区号 
	FAT16_ReadSec(temp, g_u8Fat16Buf); //读取扇区内容
	u32CurClus = u32CurClus % 256 * 2;//计算簇号在扇区的偏移量;
	return ByteUnite(&g_u8Fat16Buf[u32CurClus] , 2); //返回下一簇号

}
/*************************************************************************
*名称: FAT16_CmpFileName
*功能: 比较目录表文件名和输入的文件是否一致
*参数: pFileNameDir 目录表里的文件名,pFileNameInput输入的文件名
*返回: 零成功 非零失败
*************************************************************************/
INT8U FAT16_CmpFileName(INT8U *pFileNameDir, INT8U *pFileNameInput)
{
	INT8U temp;
	while(*pFileNameInput)
	{
		
		if(*pFileNameInput == '.') //忽略输入文件名里的.字符
		{
			pFileNameInput++;
			continue;
		}
		if(*pFileNameDir == ' ')//忽略目录表文件里的填充空格字符
		{
			pFileNameDir++;
			continue;
		}
		//将输入文件名里的小写字母转为大写
		if(*pFileNameInput > 0x60 && *pFileNameInput < 0x7B)
		{
			temp = *pFileNameInput -32;
			
		}
		else
		{
			temp = *pFileNameInput;
		}
		if(temp != *pFileNameDir++) //比较字符是否一致
		{
			return 1;
		}
		pFileNameInput++;

	}
	return 0;
}
INT32U FAT16_OpenFile(INT8U *pFileName, PFILE_INFO pg_FileInfo) 
{ 
	INT32U u32CurSec;
	INT32U u32EndSec;
	INT32U u32CurDir;
	PFAT16_DIR pDir; 
	//对根目录表所在的扇区扫描
	u32CurSec = g_Fat16InitArg.FirstDirSec; 
	
	u32EndSec = g_Fat16InitArg.FirstDirSec + g_Fat16InitArg.RootDirSz;
	for(; u32CurSec < u32EndSec; u32CurSec++) 
	{ 
		//对根目录里的目录项逐个扫描
		FAT16_ReadSec(u32CurSec, g_u8Fat16Buf); 
		for(u32CurDir = 0; u32CurDir < g_Fat16InitArg.BytesPerSec; 
				u32CurDir += 32)   
		{ 
			pDir = (PFAT16_DIR)(g_u8Fat16Buf + u32CurDir); 
			//获取一个目录表地址
			if(FAT16_CmpFileName(pDir->Name, pFileName) == 0)
							//对文件名进行匹配
			{
				INT8U i;
				pg_FileInfo->Size = ByteUnite(pDir->FileSize, 4); 
									//获取文件大小
				//strcpy(g_FileInfo.FileName,filepath+index); 
				while(*pFileName)//获取文件名
				{
					pg_FileInfo->Name[i] = *pFileName++;
					i++;
				}
				pg_FileInfo->FstClus = ByteUnite(pDir->FstClusL, 2); 
				//获取文件开始簇号
				pg_FileInfo->CurClus = pg_FileInfo->FstClus; 
				//获取文件当前簇号
				pg_FileInfo->NextClus =  	
					FAT16_GetNextClus(pg_FileInfo->CurClus);
					//获取文件的下一簇号 
				pg_FileInfo->Offset = 0; //获取偏移量
				pg_FileInfo->CurSec = (pg_FileInfo->CurClus - 2) 
				*g_Fat16InitArg.SecPerClus + g_Fat16InitArg.FirstDataSec;
				//获取当前文件的扇区号
				return 0;
			} 
	 	}
	 	
	}
	return 1;
	
}
INT32U FAT16_ReadFile(PFILE_INFO pg_FileInfo) 
{ 
	INT32U i; 
	INT32U j;
	INT32U len;
	len = pg_FileInfo->Size - pg_FileInfo->Offset; 
 	//return pg_FileInfo->CurClus;
	while(pg_FileInfo->NextClus != 0xFFFF)//循环知道没有后续簇   
	{ 
		for(i = 0; i < g_Fat16InitArg.SecPerClus; i++)//读出整簇数据 
		{ 
			FAT16_ReadSec(pg_FileInfo->CurSec + i, g_u8Fat16Buf); 
			pg_FileInfo->Offset += g_Fat16InitArg.BytesPerSec;//计算偏移量
			len = pg_FileInfo->Size - pg_FileInfo->Offset; //计算剩余字节
			for(j = 0; j < g_Fat16InitArg.BytesPerSec; j++) 
			{ 
				Uart_Printf("%s",g_u8Fat16Buf[j]);    
			} //将数据发送到串口显示
		} 
		pg_FileInfo->CurClus = pg_FileInfo->NextClus;   
		pg_FileInfo->NextClus = 
				FAT16_GetNextClus(pg_FileInfo->CurClus);
		pg_FileInfo->CurSec = (pg_FileInfo->CurClus - 2 ) 
			*g_Fat16InitArg.SecPerClus + g_Fat16InitArg.FirstDataSec;    
	} 
	while(len >= g_Fat16InitArg.BytesPerSec)    
	//处理不足一簇,而足扇区的数据 
	{ 
		FAT16_ReadSec(pg_FileInfo->CurSec++, g_u8Fat16Buf); 
		pg_FileInfo->Offset += g_Fat16InitArg.BytesPerSec;//计算偏移量
		len = pg_FileInfo->Size - pg_FileInfo->Offset; //计算剩余字节
		for(j = 0; j < g_Fat16InitArg.BytesPerSec; j++) 
		{ 
			Uart_Printf("%s",g_u8Fat16Buf[j]);
		} 
	}
	
	FAT16_ReadSec(pg_FileInfo->CurSec, g_u8Fat16Buf);
				 //读取最后一个扇区 
	for(j = 0; j < len; j++)    //输出剩余数据 
	{ 
		Uart_Printf("%s",g_u8Fat16Buf[j]); 
	} 
	return 0; 
}

⌨️ 快捷键说明

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