📄 fat.c
字号:
/****************************************Copyright (c)**************************************************
**
** 力天电子
** http://www.LT430.com
**作者:何呈
**文件名称:fat.C
**功能:
**说明:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#include <string.h>
#include "sd.h"
#include "fat.h"
#include "uart.h"
extern uchar BUFFER[512];
BYTE LONGNAME_BUFFER_ADDR[30];
BYTE DIRNAME_BUFFER_ADDR[30];
BYTE *LongNameBuffer = (BYTE *) LONGNAME_BUFFER_ADDR;
BYTE *DirNameBuffer = (BYTE *) DIRNAME_BUFFER_ADDR;
BYTE Fat32Enabled;
DWORD FirstDataSector; //根目录扇区号
WORD BytesPerSector; //每个扇区的自己数
WORD SectorsPerCluster;//每个簇的扇区数
DWORD FirstFATSector; //FAT1的扇区
DWORD SecondFATSector; //FAT2的扇区
DWORD SectorsPerFat; //每个FAT的扇区
DWORD FirstDirSector; //
DWORD FileSize;
DWORD FatInCache = 0;
//********************************************************************************************
//读一个扇区
//********************************************************************************************
void ReadBlock(DWORD LBA)
{
DWORD temp;
temp=LBA<<9;
SD_Read_Block(temp);
}
/*-----------------------------------------------------------------------
查询数据区一个簇开始扇区号
-----------------------------------------------------------------------*/
DWORD fatClustToSect(DWORD clust)
{
return ((clust-2) * SectorsPerCluster) + FirstDataSector;
}
/*-----------------------------------------------------------------------
查询一个簇所占扇区数
-----------------------------------------------------------------------*/
DWORD fatClusterSize(void)
{
// return the number of sectors in a disk cluster
return SectorsPerCluster;
}
/*-----------------------------------------------------------------------
查询SD卡文件系统信息
-----------------------------------------------------------------------*/
BYTE fatInit()
{
WORD data;BYTE t1,t2;
struct partrecord PartInfo;
struct bpb710 *bpb;
// 读MBR结构,分区表
ReadBlock(0);
// 读取分区表信息
PartInfo = *((struct partrecord *) ((struct partsector *)BUFFER)->psPart);
//FirstDataSector = PartInfo.prStartLBA;
// 读启动扇区,启动扇区号在PartInfo.prStartLBA中
delay_nus(1000); //延时
ReadBlock(PartInfo.prStartLBA); //ataReadSectors( DRIVE0, PartInfo.prStartLBA, 1, SectorBuffer );
bpb = (struct bpb710 *) ((struct bootsector710 *) BUFFER)->bsBPB;
//获取根目录扇区号
FirstDataSector = PartInfo.prStartLBA;
if(bpb->bpbFATsecs)
{
// bpbFATsecs非0,为FAT16,FAT表所占的扇区数在bpbFATsecs里
FirstDataSector += bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbFATsecs;
}
else
{
// bpbFATsecs是0,为FAT32,FAT表所占的扇区数在bpbBigFATsecs里
FirstDataSector += bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbBigFATsecs;
}
SectorsPerCluster = bpb->bpbSecPerClust;
SectorsPerFat = bpb->bpbBigFATsecs;
BytesPerSector = bpb->bpbBytesPerSec;
FirstFATSector = bpb->bpbResSectors + PartInfo.prStartLBA;
SecondFATSector = FirstFATSector+SectorsPerFat;
//查询SD卡文件系统分区类型
switch (PartInfo.prPartType)
{
case PART_TYPE_DOSFAT16:
case PART_TYPE_FAT16:
case PART_TYPE_FAT16LBA:
// 第一个目录扇区号为2
FirstDirSector = CLUST_FIRST;
//FirstDataSector += (bpb->bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;
Fat32Enabled = 0;
break;
case PART_TYPE_FAT32LBA:
case PART_TYPE_FAT32:
FirstDirSector = bpb->bpbRootClust;
Fat32Enabled = 1;
break;
default:break;
//return 1;
}
//查询SD卡文件系统信息
switch (PartInfo.prPartType)
{
case PART_TYPE_DOSFAT16:
UART0_PutString("\tDOSFAT 16\n");
break;
case PART_TYPE_FAT16:
UART0_PutString("\tFAT16 \n");
break;
case PART_TYPE_FAT16LBA:
UART0_PutString("\tFAT16 LBA\n");
break;
case PART_TYPE_FAT32LBA:
UART0_PutString("\tFAT32 LBA\n");
break;
case PART_TYPE_FAT32:
UART0_PutString("\tFAT32\n");
break;
default:
UART0_PutString("\tNo Partition!\n");
break;
}
data=PartInfo.prSize>>11; //获取容量
//打印版本号
UART0_PutString("\tFile System Version:");
UART0_PutString((char *)((struct bootsector710 *) BUFFER)->bsOEMName); //版本号
UART0_PutString("\n");
//显示磁盘容量
// data=PartInfo.prSize>>11;
//打印磁盘容量大小(单位M)
UART0_PutString("\tDisk Capacity:");
t1=data/100;
UART0_PutChar(t1+48);
data=data%100;
t1=data/10;
UART0_PutChar(t1+48);
t2=data%10;
UART0_PutChar(t2+48);
UART0_PutString("M");
return 0;
}
/*-----------------------------------------------------------------------
查询一个文件的开始簇
短文件目录用32个字节表示,结构体 direntry。一个Sector 有 512/32=16个 direntry
返回文件开始簇的地址
-------------------------------------------------------------------- ---*/
WORD baseentry = 0;
WORD entrycount = 0;
//将字符串str全部转换成大写。返回指针为str的值
char *strupr(char *str)
{
U8 i;
for(i=0;i<strlen(str);i++)
{
if(str[i]<='z' && str[i]>='a')
str[i]-='a'-'A';
}
return str;
}
//提出文件的名,和扩展名
void Analysis_filename(char *fn,char *file_N,char *file_T)
{
U8 i=0,tmp=0;
for(i=0;i<strlen(fn);i++)
{
if(fn[i]=='.')
{
file_N[i]=0;//字符串结尾
break;
}
file_N[i]=fn[i];
}
i++;
for(;i<strlen(fn);i++,tmp++)
{
file_T[tmp]=fn[i];
}
file_T[tmp+1]=0;//字符串结尾
strupr(file_N); //转换成大写
strupr(file_T); //转换成大写
}
//检查两个字符串的前n个字符是否相同
char strcmp_n(char *str1,char *str2,U8 n)
{
U8 i;
for(i=0;i<n;i++)
{
if(str1[i]!=str2[i])
break;
}
if(i==n)
return 1;
else
return 0;
}
DWORD fatGetDirEntry(DWORD entry,char *filename)
{
DWORD sector;
struct direntry *de = 0; // 防止compiler warning
struct winentry *we;
WORD hasBuffer;
WORD b;
short i,index;
BYTE *p;
char file_N[10];
char file_T[5];
Analysis_filename(filename,file_N,file_T); //解析文件名
entrycount = 0;
DirNameBuffer = 0;
// 读取目录区数据
sector = fatClustToSect(FirstDirSector);
hasBuffer = 0;
index = 16;
do
{
if(index == 16) // 是否该一人一扇区time for next sector ?
{
ReadBlock(sector++);
de = (struct direntry *)BUFFER;
index = 0;
}
if(*de->deName != 0xE5)
{
// 如果if not a deleted entry
if(de->deAttributes == ATTR_LONG_FILENAME)
{
// we have a long name entry
//长文件名
we = (struct winentry *) de;
b = 13 *( (we->weCnt-1) & 0x0f); // index into string
p = &LongNameBuffer[b];
for (i=0;i<5;i++) *p++ = we->wePart1[i*2]; // copy first part
for (i=0;i<6;i++) *p++ = we->wePart2[i*2]; // second part
for (i=0;i<2;i++) *p++ = we->wePart3[i*2]; // and third part
if (we->weCnt & 0x40) *p = 0; // in case dirnamelength is multiple of 13
if ((we->weCnt & 0x0f) == 1) hasBuffer = 1; // mark that we have a long entry
}
else //短文件名
{
// we have a short name entry
// check if this is the end of a multi-part long name entry
if(hasBuffer)
{
// a long entry name has been collected
// is it a directory ?
if(de->deAttributes == ATTR_DIRECTORY)
{
DWORD save = FirstDirSector;
DWORD save2 = baseentry;
DWORD rval;
strcpy((char *)DirNameBuffer,(char *)LongNameBuffer);
strcat((char *)DirNameBuffer,"/");
//rprintfStr(LongNameBuffer); rprintfProgStrM("/"); //EOL();
// call recursively
FirstDirSector = ((DWORD)de->deHighClust << 16) + de->deStartCluster;
rval = fatGetDirEntry(entry,filename);
FirstDirSector = save;
baseentry = save2;
if (rval)
return rval;
else
{
// reload original sector
ReadBlock(sector-1);//ataReadSectors( DRIVE0, sector-1, 1, SectorBuffer);
entrycount--; // decrement entry counter
*DirNameBuffer = 0;
}
}
else // normal file entry
if(entrycount == entry)
break;
hasBuffer = 0; // clear buffer
entrycount++; // increment entry counter
}
// else ignore short_name_only entries
}
//if(memcmp((char *)"TXT",(char *)de->deExtension,3)==0) goto SendOut;
//if((*de->deExtension==0x54) && (*(de->deExtension+1)==0x58) && (*(de->deExtension+1)==0x54)) //是txt文件
if(strcmp_n((char*)de->deName,file_N,strlen(file_N)) && strcmp_n((char*)de->deExtension,file_T,strlen(file_T)))
goto SendOut;
}
de++;
index++;
}while (*de->deName || index == 16); // 0 in de->deName[0] if no more entries
if (hasBuffer == 0) // end of entries
return 0;
SendOut:
FileSize = de->deFileSize;
return (DWORD) ((DWORD)de->deHighClust << 16) + de->deStartCluster;
}
/*-----------------------------------------------------------------------
在FAT表中查询下一个簇所在扇区号
-----------------------------------------------------------------------*/
DWORD fatNextCluster(DWORD cluster)
{
DWORD nextCluster;
DWORD fatMask;
DWORD fatOffset;
DWORD sector;
DWORD offset;
if(Fat32Enabled)
{
//一个表项为4bytes(32 bits)
fatOffset = cluster << 2;
//设置 FAT32 bit mask
fatMask = FAT32_MASK;
}
else
{
//一个表项为2bytes(16 bits)
fatOffset = cluster << 1;
//设置 FAT16 bit mask
fatMask = FAT16_MASK;
}
//计算FAT扇区号
sector = FirstFATSector + (fatOffset / BytesPerSector);
//计算FAT扇区号中表项的偏移地址
offset = fatOffset % BytesPerSector;
ReadBlock(sector);
// 读取下一个簇号
nextCluster = (*((DWORD*) &((char*)BUFFER)[offset])) & fatMask;
// 是否文件的结束簇
if (nextCluster == (CLUST_EOFE & fatMask))
nextCluster = 0;
return nextCluster;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -