📄 fat.c
字号:
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&fat文件系统函数&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//*文件名称:fat.c
//*文件作用:fat文件系统函数
//*文件作者:翟 鹏
//*创建日期:2005年5月
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
#include <include.h>
static ulong xdata DiskStart=0;//逻辑盘的起始绝对扇区号LBA
static uchar xdata SecPerClus;//逻辑盘的每簇扇区数
static uchar xdata RsvdSecCnt;//逻辑盘的保留扇区数
static uint xdata FATSz16;//FAT16逻辑盘的FAT表占用的扇区数
static ulong data position=0;//文件偏移量
uchar fat_init(void)
{
uchar data temp;
//初始化SD卡
if(SD_Init())return 1;
//读取逻辑引导扇区标志 判断是不是逻辑引导扇区
SD_Set_SectorAddr(0);
if(SD_Read_SectorByte(0,&temp))return 2;
//如果不是逻辑引导扇区 提取逻辑引导扇区号
if(temp!=0xEB && temp!=0xE9)
{
if(SD_Read_SectorByte(0x1C6,&temp))return 2;
DiskStart=temp;
if(SD_Read_SectorByte(0x1C7,&temp))return 2;
DiskStart|=(uint)temp<<8;
if(SD_Read_SectorByte(0x1C8,&temp))return 2;
DiskStart|=(ulong)temp<<16;
if(SD_Read_SectorByte(0x1C9,&temp))return 2;
DiskStart|=(ulong)temp<<24;
}
//是逻辑引导扇区 逻辑引导扇区号=0
else
{
DiskStart=0;
}
//提取逻辑盘参数
SD_Set_SectorAddr(DiskStart);
if(SD_Read_SectorByte(0x0D,&temp))return 3;SecPerClus=temp;//每簇扇区数
if(SD_Read_SectorByte(0x0E,&temp))return 3;RsvdSecCnt=temp;//逻辑盘的保留扇区数
if(SD_Read_SectorByte(0x16,&temp))return 3;FATSz16=(uint)temp;//FAT表占用扇区数
if(SD_Read_SectorByte(0x17,&temp))return 3;FATSz16|=(uint)temp<<8;//FAT表占用扇区数
return 0;
}
uint fopen(uchar *file_name, uchar *open_flag)
{
uchar data temp;
uint data StartCluster=0xFFFF;//文件的首簇
uchar data sector;
if(*open_flag=='r' && *open_flag=='w')return 0xFFFF;
//读取FAT16逻辑盘的根目录,寻找文件 通常根目录占用32个扇区
for(sector=0;sector<SecPerClus;sector++)
{
uint CurrentDir;
dog();
//遍历当前扇区
SD_Set_SectorAddr(DiskStart+RsvdSecCnt+FATSz16*2+sector);
for(CurrentDir=0;CurrentDir<512;CurrentDir+=32)
{
if(SD_Read_SectorByte(CurrentDir+0,&temp))return 0xFFFF;
if(temp==0)break;//目录结束了 跳出循环
if(temp!=0xE5)//文件没有被删除
{
if(SD_Read_SectorByte(CurrentDir+0x0B,&temp))return 0xFFFF;
if((temp&0x08)==0)//正常已知文件
{
uchar data i;
//比较文件名
for(i=0;i<11;i++)
{
if(SD_Read_SectorByte(CurrentDir+i,&temp))return 0xFFFF;
#ifdef DEBUG
DEBUG_SEND_CHAR(temp);
#endif
if(temp!=file_name[i])break;
}
#ifdef DEBUG
DEBUG_SEND_STR("\r\n");
#endif
//文件找到 提取文件的首簇
if(i==11)
{
if(SD_Read_SectorByte(CurrentDir+0x1A,&temp))return 0xFFFF;
StartCluster =(uint)temp;
if(SD_Read_SectorByte(CurrentDir+0x1B,&temp))return 0xFFFF;
StartCluster |=(uint)temp<<8;
if(StartCluster!=0xFFFF)return StartCluster;
}
}
}
}
}
if(StartCluster!=0xFFFF)return StartCluster;
return 0xFFFF;
}
void fseek(ulong offset)
{
position=offset;
}
uchar fread(char *buf, uint length, uint fp)
{
uchar data temp;
uint data ClusterOffset=fp+(position>>9)/SecPerClus;
//显示文件所有内容
while(ClusterOffset<=0xFFEF && length)
{
//计算当前簇的开始扇区
ulong data ClusterStartSector=DiskStart+RsvdSecCnt+FATSz16*2+32+(ulong)(ClusterOffset-2)*SecPerClus;
//计算当前簇内的扇区偏移量
uint data SectorOffset=(position>>9)%SecPerClus;
//循环读取32个扇区的循环变量
uchar data sector;
dog();
//判断文件为空文件
if(ClusterOffset==0)return 1;
//读取当前簇的 SecPerClus个扇区
for(sector=SectorOffset;sector<SecPerClus;sector++)
{
//当前扇区内的字节偏移量
uint data ByteOffset=position%512;
//当前扇区内的数据长度
uint data count=512-ByteOffset;
//长度不够一个扇区
if(length<count)count=length;
//读取扇区内的数据
SD_Set_SectorAddr(ClusterStartSector+sector);
if(SD_Read_Sector_Offset(ByteOffset,buf,count))return 2;
//写入和读取的位置都向后移动
buf+=count;
position+=count;
length-=count;
if(length==0)return 0;
}
//获取链接簇
SD_Set_SectorAddr(DiskStart+RsvdSecCnt+(ClusterOffset>>8));
if(SD_Read_SectorByte(ClusterOffset+ClusterOffset,&temp))return 3;
ClusterOffset=(uint)temp;
if(SD_Read_SectorByte((ClusterOffset+ClusterOffset)+1,&temp))return 4;
ClusterOffset|=(uint)temp<<8;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -