📄 fat16.c
字号:
/*************************************************************/
/* FAT16操作函数库 */
/* 环境WinAVR 20060421 */
/* 作者:Bozai(章其波) */
/* E-mail:sudazqb@163.com */
/* 2006年11月26日 */
/*************************************************************/
#include "FAT16.h"
#include "uart.h"
U16 FirstDataSector; // The first sector number of data
U16 BytesPerSector; // Bytes per sector
U16 FATsectors; // The amount sector a FAT occupied
U16 SectorsPerClust; // Sector per cluster
U16 FirstFATSector; // The first FAT sector
U16 FirstDirSector; // The first Dir sector
U16 RootDirSectors; // The sector number a Root dir occupied
U16 RootDirCount; // The count of directory in root dir
U8 (* FAT16_ReadSector)(U32,U8 *);
U8 (* FAT16_WriteSector)(U32,U8 *);
//函数指针指向sd卡的读写函数
U8 (* FAT16_ReadSector)(U32 sector, U8 * buffer)=MMC_SD_ReadSingleBlock;//device read
U8 (* FAT16_WriteSector)(U32 sector, U8 * buffer)=MMC_SD_WriteSingleBlock;//device write
struct FileInfoStruct FileInfo;//temporarily buffer for file information
//FAT16初始化,不含SD的初始化,用之前应先调用sd的初始化
unsigned char FAT16_Init()//Initialize of FAT16
{
struct bootsector50 *bs = 0;
struct bpb50 *bpb = 0;
U16 hidsec;
U8 buffer[512];
//有的sd卡BPB不在0扇区
for(hidsec=0;hidsec<0x1000;hidsec++)//Some card the BPB is not locat at secter 0
{
if(FAT16_ReadSector(hidsec,buffer))return 1;
if(buffer[0]==0xeb || buffer[0]==0xe9)break;
}
if(hidsec==0x1000)return 1; //error maybe the card hasn't been formated
bs = (struct bootsector50 *)buffer;
if(bs->bsJump[0]!=0xE9 && bs->bsJump[0]!=0xEB)return 1;
bpb = (struct bpb50 *)bs->bsBPB;
BytesPerSector = bpb->bpbBytesPerSec;//每扇区字节数
FATsectors = bpb->bpbFATsecs;//FAT占用的扇区数
SectorsPerClust = (U8)bpb->bpbSecPerClust;//每簇扇区数
FirstFATSector = bpb->bpbResSectors+hidsec;//第一个FAT表扇区
RootDirCount = bpb->bpbRootDirEnts;//根目录项数
RootDirSectors = (RootDirCount*32)>>9;//根目录占用的扇区数
FirstDirSector = FirstFATSector+bpb->bpbFATs*FATsectors;//第一个目录扇区
FirstDataSector = FirstDirSector+RootDirSectors;//第一个数据扇区
return 0;
}
//读一个簇中的一个扇区
unsigned char FAT16_LoadPartCluster(U16 cluster,unsigned part,U8 * buffer)
{
U32 sector;
sector=FirstDataSector+(U32)(cluster-2)*(U32)SectorsPerClust;//calculate the actual sector number
if(FAT16_ReadSector(sector+part,buffer))return 1;
else return 0;
}
//读整个簇
//Read the a cluster
//Not suitable for system which has few data RAM
unsigned char FAT16_LoadCluster(U16 cluster,U8 * buffer)
{
U32 sector;
unsigned char i;
sector=FirstDataSector+(U32)(cluster-2)*(U32)SectorsPerClust;//calculate the actual sector number
for(i=0;i<SectorsPerClust;i++)
{
if(FAT16_ReadSector(sector+i,buffer+(i<<9)))break;
}
if(i==SectorsPerClust)return 0;
else return 1;
}
//读下一簇簇号
//Return the cluster number of next cluster of file
//Suitable for system which has limited RAM
U16 FAT16_NextCluster(U16 cluster)
{
U8 buffer[512];
U32 sector;
U32 offset=cluster/256;
if(cluster<2)return 0xfff8;
sector=FirstFATSector+offset;//calculate the actual sector
if(FAT16_ReadSector(sector,buffer))return 0xfff8;//read fat table / return 0xfff8 when error occured
offset=cluster%256;//find the position
//offset<<=1;
//sector=buffer[offset+1];
// sector<<=8;
//sector+=buffer[offset];
sector=((U16 *)buffer)[offset];
return (U16)sector;//return the cluste number
}
//在FAT表内找空簇
//Find a free cluster return the cluster number
U16 FAT16_FindFreeCluster()
{
U8 buffer[512];
//U32 sector;
U16 i;
U16 cnt;
// sector=FirstFATSector+offset;//calculate the actual sector
//sector=FirstFATSector;
for(cnt=0;cnt<FATsectors;cnt++)//find in the FAT table
{
if(FAT16_ReadSector(FirstFATSector+cnt,buffer))return 1;//error
for(i=0;i<256;i++)
{
if(((U16 *)buffer)[i]==0x0000)break;//an unused cluster
}
if(i!=256)
{
cnt=cnt*512+i;
return cnt;//return the free cluster number
}
}
return 1;//error
}
//在cluster指向的目录下找一个空位置记录文件
//find a position to place a item withe the given directory, the parameter is FileInfo who brought the message
U16 FAT16_FindFreeItem(U16 cluster, struct FileInfoStruct *FileInfo)
{
U8 *buffer;
U32 tempclust;
U32 sector;
unsigned char cnt;
U16 offset;
// unsigned char i;
struct direntry *item = 0;
if(cluster==0)// root directory//当这个目录是根目录
{
buffer=malloc(512);//apply memory
if(buffer==0)return 1;//if failed
for(cnt=0;cnt<RootDirSectors;cnt++)
{
if(FAT16_ReadSector(FirstDirSector+cnt,buffer)){free(buffer);return 1;}//read sector
for(offset=0;offset<512;offset+=32)
{
item=(struct direntry *)(&buffer[offset]);
//used item
if((item->deName[0] != 0x00) & (item->deName[0] != 0xe5) & (item->deAttributes != 0x0f));
//unused item
else
{
FileInfo->StartCluster = item->deStartCluster;//don't care
FileInfo->Size = item->deFileSize;//don't care
FileInfo->Attr = item->deAttributes;//don't care
FileInfo->Sector = FirstDirSector+cnt;//The key parameter record the secoter nuber which the item stored
FileInfo->Offset = offset; //The key parameter record the offset in the sector
free(buffer);//realease
return 0;//done
}
}
}
free(buffer);//release
}
else//other folders//当这是一个其它目录时,程序暂且没考虑到目录内没有空余项是需要另找一个簇来记录
{
tempclust=cluster;
while(1)
{
sector=FirstDataSector+(tempclust-2)*SectorsPerClust;//calculate the actual sector number
buffer=malloc(512);//apply memory
if(buffer==0)return 1;//if failed
for(cnt=0;cnt<SectorsPerClust;cnt++)
{
if(FAT16_ReadSector(sector+cnt,buffer)){free(buffer);return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntry *)(&buffer[offset]);
if((item->deName[0] != 0x2e) & (item->deName[0] != 0x00) & (item->deName[0] != 0xe5) & (item->deAttributes != 0x0f));
else
{
FileInfo->StartCluster = item->deStartCluster;
FileInfo->Size = item->deFileSize;
FileInfo->Attr = item->deAttributes;
FileInfo->Sector = sector+cnt;
FileInfo->Offset = offset;
free(buffer);
return 0;
}
}
}
free(buffer);//release
tempclust=FAT16_NextCluster(tempclust);//next cluster
if(tempclust == 0xffff || tempclust == 0xfff8)return 1;
}
}
return 1;
}
//显示给定路径下的文件
//display the content of a foler , 0 as root directory
unsigned char FAT16_DisDir(U8 *dir)
{
U8 *buffer;
U32 sector;
U16 cluster;
U32 tempclust;
unsigned char cnt;
U16 offset;
unsigned char i;
struct direntry *item = 0;
cluster = FAT16_OpenDir(dir);
if(cluster == 1)return 1;
if(cluster==0)// root directory
{
buffer=malloc(512);//apply memory
if(buffer==0)return 1;//if failed
for(cnt=0;cnt<RootDirSectors;cnt++)
{
if(FAT16_ReadSector(FirstDirSector+cnt,buffer)){free(buffer);return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntry *)(&buffer[offset]);//pointer convert
//find a valid item and display it
if((item->deName[0] != '.') & (item->deName[0] != 0x00) & (item->deName[0] != 0xe5) & (item->deAttributes != 0x0f))
{
USART_putchar(0x0d);
USART_putchar(0x0a);
for(i=0;i<8;i++)//name
{
USART_putchar(item->deName[i]);
}
if((item->deAttributes & 0x10)==0)USART_putchar('.');
for(i=0;i<3;i++)//extention
{
USART_putchar(item->deExtension[i]);
}
}
}
}
free(buffer);//release
}
else//other folders
{
tempclust=cluster;
while(1)
{
sector=FirstDataSector+(U32)(tempclust-2)*(U32)SectorsPerClust;//calculate the actual sector number
buffer=malloc(512);//apply memory
if(buffer==0)return 1;//if failed
for(cnt=0;cnt<SectorsPerClust;cnt++)
{
if(FAT16_ReadSector(sector+cnt,buffer)){free(buffer);return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntry *)(&buffer[offset]);
if((item->deName[0] != '.') & (item->deName[0] != 0x00) & (item->deName[0] != 0xe5) & (item->deAttributes != 0x0f))
{
USART_putchar(0x0d);
USART_putchar(0x0a);
for(i=0;i<8;i++)
{
USART_putchar(item->deName[i]);
}
if((item->deAttributes & 0x10)==0)USART_putchar('.');
for(i=0;i<3;i++)
{
USART_putchar(item->deExtension[i]);
}
}
}
}
free(buffer);//release
tempclust=FAT16_NextCluster(tempclust);//next cluster
if(tempclust == 0xffff)break;
}
}
return 0;
}
//在给定目录下查找文件
//Find a item in the directory which specify by the parameter "cluster"
//Return the start cluster number
U16 FAT16_FindItem(U16 cluster, U8 *name, struct FileInfoStruct *FileInfo)
{
U8 *buffer;
U32 tempclust;
U32 sector;
unsigned char cnt;
U16 offset;
unsigned char i;
struct direntry *item = 0;
if(cluster==0)// root directory
{
buffer=malloc(512);//apply memory
if(buffer==0)return 1;//if failed
for(cnt=0;cnt<RootDirSectors;cnt++)
{
if(FAT16_ReadSector(FirstDirSector+cnt,buffer)){free(buffer);return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntry *)(&buffer[offset]);
if((item->deName[0] != 0x00) & (item->deName[0] != 0xe5) & (item->deAttributes != 0x0f))
{
for(i=0;i<11;i++)
{
if(buffer[offset+i]!=name[i])break;
}
if(i==11)
{
//return the parameter of the item
FileInfo->StartCluster = item->deStartCluster;
FileInfo->Size = item->deFileSize;
FileInfo->Attr = item->deAttributes;
FileInfo->Sector = FirstDirSector+cnt;
FileInfo->Offset = offset;
free(buffer);
return 0;
}
}
}
}
free(buffer);//release
}
else//other folders
{
tempclust=cluster;
while(1)
{
sector=FirstDataSector+(U32)(tempclust-2)*(U32)SectorsPerClust;//calculate the actual sector number
buffer=malloc(512);//apply memory
if(buffer==0)return 1;//if failed
for(cnt=0;cnt<SectorsPerClust;cnt++)
{
if(FAT16_ReadSector(sector+cnt,buffer)){free(buffer);return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntry *)(&buffer[offset]);
if((item->deName[0] != 0x00) & (item->deName[0] != 0xe5) & (item->deAttributes != 0x0f))
{
for(i=0;i<11;i++)
{
if(buffer[offset+i]!=name[i])break;
}
if(i==11)
{
FileInfo->StartCluster = item->deStartCluster;
FileInfo->Size = item->deFileSize;
FileInfo->Attr = item->deAttributes;
FileInfo->Sector = sector+cnt;
FileInfo->Offset = offset;
free(buffer);
return 0;
}
}
}
}
free(buffer);//release
tempclust=FAT16_NextCluster(tempclust);//next cluster
if(tempclust == 0xffff || tempclust == 0xfff8)break;
}
}
return 1;
}
//挑选一个未使用的记录项
//select the first unsed item in the given cluster
//for delete a foler or a file
unsigned char FAT16_SelectOneItem(U16 cluster,struct FileInfoStruct *FileInfo)
{
U8 *buffer;
U32 tempclust;
U32 sector;
unsigned char cnt;
U16 offset;
// unsigned char i;
struct direntry *item = 0;
if(cluster==0)// root directory
{
buffer=malloc(512);//apply memory
if(buffer==0)return 1;//if failed
for(cnt=0;cnt<RootDirSectors;cnt++)
{
if(FAT16_ReadSector(FirstDirSector+cnt,buffer)){free(buffer);return 1;}
for(offset=0;offset<512;offset+=32)
{
item=(struct direntry *)(&buffer[offset]);
if((item->deName[0] != 0x00) & (item->deName[0] != 0xe5) & (item->deAttributes != 0x0f))
{
//return the parameter of the item
FileInfo->StartCluster = item->deStartCluster;
FileInfo->Size = item->deFileSize;
FileInfo->Attr = item->deAttributes;
FileInfo->Sector = FirstDirSector+cnt;
FileInfo->Offset = offset;
free(buffer);
return 0;
}
}
}
free(buffer);//release
}
else//other folders
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -