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

📄 fat16.c

📁 FAT的C语言原代码,没有底层驱动,支持打开文件,读写文件,不支持长文件名.
💻 C
字号:
#include "mcutypes.h"
#include "FAT16.h"

#if USE_FAT

typedef struct
{
	uint16 m;
	uint16 ClusID;
	uint32 i;
	uint32 LBA;
} FATFileIndex;

static uint8           BUFFER[512];      //512字节的缓冲区

static FATFileIndex    FileIndex;        //当前打开的文件
static uint8           BPB_SecPerClus;
static uint16          BPB_RsvdSecCnt;
static uint8           BPB_NumFATs;
static uint16          BPB_RootEntCnt;
static uint16          BPB_TotSec16;
static uint16          BPB_FATSz16;
static uint32          BPB_HiddSec;

static void     ReadBlock        (uint32 LBA);
#if !FAT_READ_ONLY
static void     WriteBlock       (uint32 LBA);
#endif
static uint8    IsEqual          (void* A, void* B, uint8 Size);
static void     ReadBPB          (void);
static uint32   ClusConvLBA      (uint16 ClusID);
static uint16   ReadFAT          (uint16 Index);
static uint8    GetFileID        (uint8 Name[11], DIR* ID);

void FAT_Init(void)
{
	ReadBPB();
}

//********************************************************************************************
//读一个扇区
static void ReadBlock(uint32 LBA)
//********************************************************************************************
{
	MMC_read_sector(LBA + 39, BUFFER);
}

#if !FAT_READ_ONLY
//********************************************************************************************
//写一个扇区
static void WriteBlock(uint32 LBA)
//********************************************************************************************
{
	MMC_write_sector(LBA + 39, BUFFER);
}
#endif

//********************************************************************************************
static uint8 IsEqual(void* A, void* B, uint8 Size)
//********************************************************************************************
{
	uint8 i, *a = A, *b = B;
	for(i = 0; i < Size; i++)
		if(a[i] != b[i])
			return 0;
	return 1;
}

//********************************************************************************************
//读取BPB数据结构
static void ReadBPB(void)
//********************************************************************************************
{
	FAT_BPB* BPB = (FAT_BPB*)BUFFER;
	ReadBlock(0);

	//缓存相关参数
	BPB_SecPerClus  =  BPB->BPB_SecPerClus;
	BPB_RsvdSecCnt  =  BPB->BPB_RsvdSecCnt;
	BPB_NumFATs     =  BPB->BPB_NumFATs;
	BPB_RootEntCnt  =  BPB->BPB_RootEntCnt;
	BPB_TotSec16    =  BPB->BPB_TotSec16;
	BPB_FATSz16     =  BPB->BPB_FATSz16;
	BPB_HiddSec     =  BPB->BPB_HiddSec;

}

//********************************************************************************************
//获取根目录开始扇区号
static uint32 DirStartSec(void)
//********************************************************************************************
{
	return BPB_RsvdSecCnt + BPB_NumFATs * BPB_FATSz16;
}

//********************************************************************************************
//获取数据区开始扇区号
static uint32 DataStartSec(void)
//********************************************************************************************
{
	return DirStartSec() + BPB_RootEntCnt * 32 / 512;
}

//********************************************************************************************
//目录项占用的扇区数
static uint16 GetDirSecCount(void)
//********************************************************************************************
{
	return BPB_RootEntCnt * 32 / 512;
}

//********************************************************************************************
//获取一个簇的开始扇区
static uint32 ClusConvLBA(uint16 ClusID)
//********************************************************************************************
{
	return DataStartSec() + BPB_SecPerClus * (ClusID - 2);
}

//********************************************************************************************
//读取文件分配表的指定项
static uint16 ReadFAT(uint16 Index)
//********************************************************************************************
{
	uint16 *RAM = (uint16*)BUFFER;
	ReadBlock(BPB_RsvdSecCnt + Index / 256);
	return RAM[Index % 256];
}

//********************************************************************************************
//获得和文件名对应的目录项
static uint8 GetFileID(uint8 Name[11], DIR* ID)
//********************************************************************************************
{
	uint16 DirSecCut, DirStart, i, m;
	DirSecCut = GetDirSecCount();
	DirStart = DirStartSec();
	for(i = 0; i < DirSecCut; i++)
	{
		ReadBlock(DirStart + i);
		for(m = 0; m <16; m++)
		{
			if(IsEqual(Name, &((DIR*)&BUFFER[m * 32])->FileName, 11))
			{
				*ID = *((DIR*)&BUFFER[m * 32]);
				return 1; //找到对应的目录项,返回1
			}
		}
	}
	return 0; //没有找到对应的目录项,返回0
}

//********************************************************************************************
//打开指定文件
void FAT_FileOpen(uint8 Name[11], uint32 Start)
//********************************************************************************************
{
	uint16 BytePerClus, ClusNum;
	DIR FileDir;
	BytePerClus = BPB_SecPerClus * 512; // 每簇的字节数
	GetFileID(Name, &FileDir);

	//计算开始位置所在簇的簇号
	ClusNum = Start / BytePerClus;
	FileIndex.ClusID = FileDir.FilePosit.Start;
	for(FileIndex.i = 0; FileIndex.i < ClusNum; FileIndex.i++)
		FileIndex.ClusID = ReadFAT(FileIndex.ClusID);


	FileIndex.i = (Start % BytePerClus) / 512; //开始位置所在扇区簇内偏移
	FileIndex.m = (Start % BytePerClus) % 512; //开始位置扇区内偏移

	FileIndex.LBA = ClusConvLBA(FileIndex.ClusID) + FileIndex.i; //开始位置所在的扇区号
	ReadBlock(FileIndex.LBA); //预读取一个扇区的内容
}

//********************************************************************************************
//读取文件的数据
void FAT_FileRead(uint32 Length, void* Data)
//********************************************************************************************
{
	uint8 *data = Data;

	goto FAT_FileRead_Start;

	while(1)
	{
		FileIndex.ClusID = ReadFAT(FileIndex.ClusID); //下一簇簇号
		FileIndex.LBA = ClusConvLBA(FileIndex.ClusID);
		FileIndex.i = 0;
		while(FileIndex.i < BPB_SecPerClus)
		{
			ReadBlock(FileIndex.LBA);
			FileIndex.m = 0;
FAT_FileRead_Start:
			while(FileIndex.m < 512)
			{
				*data++ = BUFFER[FileIndex.m];
				FileIndex.m++;
				//如果读取完成就退出
				if(--Length == 0)
					return;
			}
			FileIndex.LBA++;
			FileIndex.i++;
		}
	}
}

#if !FAT_READ_ONLY
//********************************************************************************************
//写文件的数据
void FAT_FileWrite(uint32 Length, void* Data)
//********************************************************************************************
{
	uint8 *data = Data;

	goto FAT_FileWrite_Start;

	while(1)
	{
		FileIndex.ClusID = ReadFAT(FileIndex.ClusID); //下一簇簇号
		FileIndex.LBA = ClusConvLBA(FileIndex.ClusID);
		FileIndex.i = 0;
		while(FileIndex.i < BPB_SecPerClus)
		{
			ReadBlock(FileIndex.LBA);
			FileIndex.m = 0;
FAT_FileWrite_Start:			
			while(FileIndex.m < 512)
			{
				BUFFER[FileIndex.m] = *data++;
				FileIndex.m++;
				//如果读取完成就退出
				if(--Length == 0)
				{
					WriteBlock(FileIndex.LBA); //回写扇区
					return;
				}
			}
			WriteBlock(FileIndex.LBA++); //回写扇区,指针下移
			FileIndex.i++;
		}
	}
}
#endif
//---------------------------------------------------------------------------------------------------------------------------------
#endif

⌨️ 快捷键说明

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