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

📄 fat.c

📁 基于SPI方式的MMC卡的FAT代码,可修改用于SD卡的管理.
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********************************************************************************************
**
**	Copyright(c) Semitek
**
**	模 块 名:fat.c
**
**	模块功能:实现有关FAT16文件系统的操作
**
**	修改日期:2007年4月5日
**
**********************************************************************************************/
#include "fat.h"

BYTE cluster_size = 0;//每簇的扇区数
WORD sector_size = 0;//每扇区的字节数
DWORD RootDir_Start_SecNum = 0;//根目录开始扇区号
DWORD Data_Start_SecNum = 0;//数据区开始扇区号
DWORD FAT1_Start_SecNum = 0;//FAT1开始扇区号
DWORD FAT2_Start_SecNum = 0;//FAT2开始扇区号

WORD DIR_FstClusHI = 0;//起始簇号的高16位
WORD DIR_FstClusLO = 0;//起始簇号的低16位

DWORD EmptyCluster = 0;//FAT中空闲的簇号

DWORD TotalSector = 0;


DWORD WriteData_Addr = 0;//写数据地址

extern BYTE MMCRDData[MMC_DATA_SIZE];
extern BYTE MMCWRData[MMC_DATA_SIZE];

/**********************************************************************************************
**
**	函数名称:GetFatInfo
**
**	函数功能:读MMC的0扇区,获得有关FAT的基本信息
**
**	输入参数:无
**
**	返 回 值:无
**
**	影响参数:cluster_size,fat_offset,cluster_offset,RootDir_Start_SecNum,Data_Start_SecNum
**
**	调用模块:mmc_read_block()
**
**	说    明:无
**
**********************************************************************************************/
void GetFatInfo()
{
	BYTE	BS_jmpBoot[3];	//跳转指令
	BYTE	BS_OEMName[8];	//制造商名称
	WORD	BPB_BytesPerSec;//字节/扇区
	BYTE	BPB_SecPerClus;	//扇区/簇
	WORD	BPB_RsvdSecCnt;	//保留扇区数
	BYTE	BPB_NumFATs;	//FAT表数目
	WORD	BPB_RootEntCnt;	//根目录项数
	WORD	BPB_TotSec16;	//小于32MB的扇区数
	BYTE	BPB_Media;		//媒体描述符
	WORD	BPB_FATSz16;	//每个FAT表所占扇区数
	WORD	BPB_SecPerTrk;	//每磁道上的扇区数
	WORD	BPB_NumHeads;	//磁头数
	
	DWORD	BPB_HiddSec;	//隐藏扇区数
	DWORD	BPB_TotSec32;	//大于32MB的扇区数

	mmc_read_block(MASTER_BOOT_RECORD);
	
	BPB_BytesPerSec = MMCRDData[OFFSET_BPB_BytesPerSec] | (MMCRDData[OFFSET_BPB_BytesPerSec+1]<<8);
	BPB_SecPerClus  = MMCRDData[OFFSET_BPB_SecPerClus];
	BPB_RsvdSecCnt  = MMCRDData[OFFSET_BPB_RsvdSec] | (MMCRDData[OFFSET_BPB_RsvdSec+1]<<8);
	BPB_NumFATs	    = MMCRDData[OFFSET_BPB_NumFATs];
	BPB_RootEntCnt  = MMCRDData[OFFSET_BPB_RootEntCnt] | (MMCRDData[OFFSET_BPB_RootEntCnt+1]<<8);
	BPB_TotSec16	= MMCRDData[OFFSET_BPB_TotSec16] | (MMCRDData[OFFSET_BPB_TotSec16+1]<<8);
	BPB_Media	    = MMCRDData[OFFSET_BPB_Media];
	BPB_FATSz16	    = MMCRDData[OFFSET_BPB_FATSz16] | (MMCRDData[OFFSET_BPB_FATSz16+1]<<8);
	BPB_SecPerTrk   = MMCRDData[OFFSET_BPB_SecPerTrk] | (MMCRDData[OFFSET_BPB_SecPerTrk+1]<<8);
	BPB_NumHeads	= MMCRDData[OFFSET_BPB_NumHeads] | (MMCRDData[OFFSET_BPB_NumHeads+1]<<8);
	BPB_HiddSec	    = MMCRDData[OFFSET_BPB_HiddSec] | (MMCRDData[OFFSET_BPB_HiddSec+1]<<8) | (MMCRDData[OFFSET_BPB_HiddSec+2]<<16) | (MMCRDData[OFFSET_BPB_HiddSec+3]<<24);
	BPB_TotSec32	= MMCRDData[OFFSET_BPB_TotSec32] | (MMCRDData[OFFSET_BPB_TotSec32+1]<<8) | (MMCRDData[OFFSET_BPB_TotSec32+2]<<16) | (MMCRDData[OFFSET_BPB_TotSec32+3]<<24);

	RootDir_Start_SecNum = BPB_RsvdSecCnt + (BPB_NumFATs * BPB_FATSz16);

	Data_Start_SecNum = RootDir_Start_SecNum + (32*BPB_RootEntCnt + (BPB_BytesPerSec -1))/BPB_BytesPerSec;

	cluster_size = BPB_SecPerClus;

	sector_size = BPB_BytesPerSec;

	FAT1_Start_SecNum = BPB_RsvdSecCnt;
	
	FAT2_Start_SecNum = BPB_RsvdSecCnt + BPB_FATSz16;

	TotalSector = BPB_TotSec32;

	return;
}




/**********************************************************************************************
**
**	函数名称:UpDataRootDir
**
**	函数功能:更新根目录内容
**
**	输入参数:文件名,文件大小
**
**	返 回 值:暂无
**
**	影响参数:暂无
**
**	调用模块:mmc_read_block,mmc_write_block
**
**	说    明:根目录是以32字节为单位进行读写,读写前要将文件名转换成大写字母
**
**********************************************************************************************/
void UpDataRootDir(BYTE *Name,DWORD FileSize,BYTE FileAttrib)
{
	BYTE Buffer[11];
	BYTE i,j,k = 0;

	for(i=0;i<8;i++)
	{		
		if(*Name != '.' && *Name != '\0') 
		{
			Buffer[i] = *Name;
		}
		else
		{
			goto Label;
		}
		Name++;
		Label:	Buffer[i+1] = 0x20;
	}
	for(i=0;i<3;i++)
	{
		Name++;
		if(*Name != 0)	Buffer[i+8] = *Name;
		else	Buffer[i+8] = 0x20;
	}

 	mmc_read_block(RootDir_Start_SecNum);

	for(i=0;i<16;i++)
	{
		if(MMCRDData[i*32] == 0x00 || MMCRDData[i*32] == 0xE5)
		{
		 	break;
		}
	}
			
	k = i << 5;
	for(j=0;j<11;j++)
		MMCRDData[k + j] = Buffer[j];//主文件名+扩展文件名,为8.3格式

	MMCRDData[k + 11] = FileAttrib;//文件属性

	MMCRDData[k + 12] = 0x00;//仅长文件名目录使用,对于FAT16不使用
	MMCRDData[k + 13] = 0x00;

	MMCRDData[k + 14] = 0X79;//文件建立时间
	MMCRDData[k + 15] = 0X6C;

	MMCRDData[k + 16] = 0X85;//文件建立日期
	MMCRDData[k + 17] = 0X36;

	MMCRDData[k + 18] = 0x85;//文件最近访问日期
	MMCRDData[k + 19] = 0x36;

	MMCRDData[k + 20] = 0x00;//系统保留
	MMCRDData[k + 21] = 0x00;

	MMCRDData[k + 22] = 0x68;//最新修改时间
	MMCRDData[k + 23] = 0X77;
		     
	MMCRDData[k + 24] = 0x83;//最新修改日期
	MMCRDData[k + 25] = 0x36;

	MMCRDData[k + 26] = (DIR_FstClusLO & 0x00FF) >> 0x00;//起始簇号16位
	MMCRDData[k + 27] = (DIR_FstClusLO & 0xFF00) >> 0x08;

	MMCRDData[k + 28] = (FileSize & 0x000000FF) >> 0x00;//文件大小
	MMCRDData[k + 29] = (FileSize & 0x0000FF00) >> 0x08;
	MMCRDData[k + 30] = (FileSize & 0x00FF0000) >> 0x10;
	MMCRDData[k + 31] = (FileSize & 0xFF000000) >> 0x18;

	mmc_write_block(RootDir_Start_SecNum,MMCRDData);

	return;
}



/**********************************************************************************************
**
**	函数名称:FATGetNextClus
**
**	函数功能:返回FAT表指定簇的下一个簇号
**
**	输入参数:从FAT表中读到的数组
**
**	返 回 值:下一个簇号
**
**	影响参数:暂无
**
**	调用模块:暂无
**
**	说    明:暂无
**
**********************************************************************************************/
DWORD FATGetNextClus(BYTE *Buf)
{
	WORD i;

	for(i=0;i<512;i+=2)
	{
		if(*(Buf+i) == 0xFF && *(Buf+i+1)== 0xFF && *(Buf+i+2) == 0x00 && *(Buf+i+3) == 0x00) break;
	}
	return ((i+2) >> 1);
}



/**********************************************************************************************
**
**	函数名称:UpDataFAT
**
**	函数功能:更新FAT表
**
**	输入参数:文件大小
**
**	返 回 值:暂无
**
**	影响参数:暂无
**
**	调用模块:mmc_read_block,mmc_write_block,FATGetNextClus
**
**	说    明:FAT表是个链表,在根目录中得到簇号,然后根据文件所占的簇数进行写入
**
**********************************************************************************************/
void UpDataFAT(DWORD FileSize)
{
	DWORD File_TolCluster = 0;
	WORD i = 0,j = 0,k = 0,cluster = 0;

	for(k=0;k<64;k++)
	{
		mmc_read_block(FAT1_Start_SecNum+k);
	
		if(k ==0)
		{
			EmptyCluster = FATGetNextClus(MMCRDData);
			j = EmptyCluster+1;
			cluster = EmptyCluster;
		}
		for(i = 0;i < 512;i += 2)
		{
			cluster++;
			if(k == 0)
			{
				MMCRDData[i+4] = cluster & 0x00FF;
				MMCRDData[i+5] = (cluster & 0xFF00) >> 8;
				if(i == 506) break;
			}
			else
			{
				MMCRDData[i] = cluster & 0x00FF;
				MMCRDData[i+1] = (cluster & 0xFF00) >> 8;
			}
		}
		if(k == 63)
		{
			MMCRDData[i-2] = 0xFF;
			MMCRDData[i-1] = 0xFF;
		}
		mmc_write_block(FAT1_Start_SecNum+k,MMCRDData);
		mmc_write_block(FAT2_Start_SecNum+k,MMCRDData);
	}

	DIR_FstClusHI = (EmptyCluster & 0xFFFF0000) >> 0x10;
	DIR_FstClusLO = (EmptyCluster & 0x0000FFFF) >> 0x00;

	File_TolCluster = FileSize >> 0x0A;	 //文件所占的簇数 = 文件大小 >> 10
	WriteData_Addr = Data_Start_SecNum + (EmptyCluster - 2) * sector_size;//文件内容所写的地址=数据区起始扇区号+(簇号-2)*每扇区所占字节数

	return;
}

/**********************************************************************************************
**
**	函数名称:CreateFile
**
**	函数功能:创建以FileName为文件名、WriteData为文件内容的文件
**
**	输入参数:FileName->文件名;WriteData->待写数据
**
**	返 回 值:暂无
**
**	影响参数:暂无
**
**	调用模块:UpDataFAT,UpDataRootDir,WriteFile
**
**	说    明:创建文件流程:WriteFat->WriteRootDir->WriteData
**
**********************************************************************************************/
void CreateFile(BYTE *FileName,BYTE *WriteData,DWORD FileSize)
{
	BYTE Rt,Name_Buffer[12];
	DWORD Time=0,LastAddr = 0;

	memcpy(Name_Buffer,FileName,12);

	strupr(Name_Buffer);

	Time = GetRecord();
	LastAddr = FindFileEnd();
	Rt = ChkFileExist(Name_Buffer);
	if(Rt == 0)//文件不存在,新建文件并写入数据
	{
		UpDataFAT(FileSize);//写FAT表

		UpDataRootDir(Name_Buffer,FileSize,0x01);//写根目录

		WriteFile(WriteData_Addr,FileSize,WriteData);//写数据

⌨️ 快捷键说明

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