📄 fat16.c
字号:
/* Includes ------------------------------------------------------------------*/
#include "config.h"
#include "FAT16.h"
/* Global declare -------------------------------------------------------------*/
typedef __packed struct
{
u16 ByteOff;
u16 ClusID;
u32 SecOff;
u32 LBA;
u32 HaveReadByte;
} FATFileIndex;
u8 SystemID; // 分区类型
u32 RelativeSectors; // 分区起始扇区数,指分区相对于记录该分区的分区表的扇区位置之差 (该分区表:LBA=0x0)。
u32 TotalSectors; // 分区总扇区数
u8 BUFFER[512]; // 512字节的缓冲区
u16 ClusterNum;
FATFileIndex FileIndex; // 当前打开的文件
u8 BPB_SecPerClus;
u16 BPB_RsvdSecCnt;
u8 BPB_NumFATs;
u16 BPB_RootEntCnt;
u16 BPB_TotSec16;
u16 BPB_FATSz16;
u32 BPB_HiddSec;
u16 BPB_BytesPerSec ;
/* Fuction declare ------------------------------------------------------------*/
void ReadBlock (u32 LBA);
u8 IsEqual (void* A, void* B, u8 Size);
void ReadMBR (void);
void ReadBPB (void);
u32 ClusConvLBA (u16 ClusID);
u16 LBAConvClus(u32 LBA);
u16 ReadFAT (u16 Index);
void GetFileName(u32 secAddr, u16 secNumOff, u8 persecdirOff, u8 filename[], u8 *len);
/* Extern declare -------------------------------------------------------------*/
extern u16 UnicodeToGB2312(u16 unicode); // 用二分查找算法
extern u8 MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead);
/* Function define ------------------------------------------------------------*/
/*******************************************************************************
* Function Name : FAT_Init
* Description : Init the FAT16 File System.
* Input : Mone
* Output : None
* Return : None
*******************************************************************************/
void FAT_Init(void)
{
ReadMBR();
ReadBPB();
}
/*******************************************************************************
* Function Name : ReadBlock
* Description : Read a block from the sd card
* Input : LBA--the sd card address
* Output : None
* Return : None
*******************************************************************************/
static void ReadBlock(u32 LBA)
{
MSD_ReadBlock(BUFFER,LBA*512,512);
}
/*******************************************************************************
* Function Name : IsEqual
* Description : Compare the two strings
* Input : A--one string,B--the other string
* Output : None
* Return : 0-- not equal, 1--equal
*******************************************************************************/
static u8 IsEqual(void* A, void* B, u8 Size)
{
u8 i, *a = A, *b = B;
for(i = 0; i < Size; i++)
if(a[i] != b[i])
return 0;
return 1;
}
/*******************************************************************************
* Function Name : ReadMBR
* Description : Read the sd card's first block--MBR
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void ReadMBR(void)
{
MBR_tag* MBR = (MBR_tag*)BUFFER;
ReadBlock(0);
//缓存相关参数
SystemID = MBR->PT[0].SystemID;
RelativeSectors = MBR->PT[0].RelativeSectors;
TotalSectors = MBR->PT[0].TotalSectors;
}
/*******************************************************************************
* Function Name : ReadBPB
* Description : Read BPB struct
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void ReadBPB(void)
{
FAT_BPB* BPB = (FAT_BPB*)BUFFER;
ReadBlock(RelativeSectors);
//缓存相关参数
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;
BPB_BytesPerSec = BPB->BPB_BytesPerSec;
}
/*******************************************************************************
* Function Name : DirStartSec
* Description : Get the root directory's sector No.
* Input : None
* Output : None
* Return : Root directory's sector No.
*******************************************************************************/
u32 DirStartSec(void)
{
return RelativeSectors + BPB_RsvdSecCnt + BPB_NumFATs * BPB_FATSz16;
}
/*******************************************************************************
* Function Name : DataStartSec
* Description : Get the data area's start sector NO.
* Input : None
* Output : None
* Return : The data area's start sector NO.
*******************************************************************************/
static u32 DataStartSec(void)
{
return DirStartSec() + BPB_RootEntCnt * 32 / 512;
}
/*******************************************************************************
* Function Name : ClusConvLBA
* Description : Get one cluster's first sector NO.
* Input : The cluster's NO.
* Output : None
* Return : The cluster's first sector NO.
*******************************************************************************/
static u32 ClusConvLBA(u16 ClusID)
{
return DataStartSec() + BPB_SecPerClus * (ClusID - 2);
}
/*******************************************************************************
* Function Name : LBAConvClus
* Description : Convert from sector NO. to cluster NO.
* Input : The cluster's NO.
* Output : None
* Return : The cluster NO.
*******************************************************************************/
static u16 LBAConvClus(u32 LBA)
{
return (LBA - DataStartSec()) / BPB_SecPerClus + 2;
}
/*******************************************************************************
* Function Name : ReadFAT
* Description : Read the value of FAT table
* Input : The FAT table's index
* Output : None
* Return : The value of assigned FAT index
*******************************************************************************/
static u16 ReadFAT(u16 Index)
{
u16 *RAM = (u16*)BUFFER;
ReadBlock(RelativeSectors + BPB_RsvdSecCnt + Index / 256);
return RAM[Index % 256];
}
/*******************************************************************************
* Function Name : CalcuFreeSpace
* Description : Calculate the free space
* Input : None
* Output : None
* Return : The free space num(in bytes)
*******************************************************************************/
u32 CalcuFreeSpace()
{
u32 size;
u16 i, j;
u16 *RAM = (u16*)BUFFER;
size = 0;
//BPB_FATSz16
for(i = 0 ; i < BPB_FATSz16 ; i++)
{
ReadBlock(RelativeSectors + BPB_RsvdSecCnt + i);
for(j = 0; j < 256; j++)
{
if(RAM[j] == 0x00)//空闭簇
size += BPB_SecPerClus * BPB_BytesPerSec;
}
}
return size;
}
/*******************************************************************************
* Function Name : GetFileName
* Description : Get the file name
* Input : secAddr--指所要找文件名的首扇区地址
secNumOff--指相对首扇区的偏移
persecdirOff--指在扇区内目录项的偏移
filename[]--the file name
len--the file name length
* Output : None
* Return : None
*******************************************************************************/
void GetFileName(u32 secAddr, u16 secNumOff, u8 persecdirOff, u8 filename[], u8 *len)
{
u8 i,k;
DIR *ID;
u16 tmp ,GB2312;
signed char j;
*len = 0;
if(persecdirOff == 0) //当短文件名在扇区的第一目录项时,由于需要以上一目录项来判断是否有长文件名,需要特殊处理
{
ReadBlock(secAddr + secNumOff - 1);
if( BUFFER[15 * 32 + 0xB] == 0x0F) //该文件有长文件名
persecdirOff = 16;//从上一扇区的最后一个目录项开始读(长文件的目录项是倒放在扇区中)
else
ReadBlock(secAddr + secNumOff);//该文件无长名,需要返回原来扇区读短文件名
}
if( BUFFER[(persecdirOff - 1) * 32 + 0xB] == 0x0F) //该文件有长文件名
{
k = persecdirOff;
while(1)
{
ID = (DIR*)(&BUFFER[(k - 1) * 32]);
//从长文件目录项中读取文件名,每个长目录分3个区域存放
for(i = 0x1 ; i <= 0xA; i+=2)
{
tmp = *(((u8 *)ID) + i) + (*(((u8 *)ID) + i + 1) << 8);
GB2312 = UnicodeToGB2312(tmp); //将对应的Unicode码转化为GB2312码
if(((GB2312 & 0xFF00) != 0) && ((GB2312 & 0xFF00) != 0xFF00))//去掉0和FF
filename[(*len)++] = (GB2312 & 0xFF00) >> 8;
if(((GB2312 & 0x00FF) != 0) && ((GB2312 & 0x00FF) != 0x00FF))
filename[(*len)++] = (GB2312 & 0x00FF);
}
for(i = 0xE ; i <= 0x19; i+=2)
{
tmp = *(((u8 *)ID) + i) + (*(((u8 *)ID) + i + 1) << 8);
GB2312 = UnicodeToGB2312(tmp); //将对应的Unicode码转化为GB2312码
if(((GB2312 & 0xFF00) != 0) && ((GB2312 & 0xFF00) != 0xFF00))//去掉0和FF
filename[(*len)++] = (GB2312 & 0xFF00) >> 8;
if(((GB2312 & 0x00FF) != 0) && ((GB2312 & 0x00FF) != 0x00FF))
filename[(*len)++] = (GB2312 & 0x00FF);
}
for(i = 0x1C ; i <= 0x1F; i+=2)
{
tmp = *(((u8 *)ID) + i) + (*(((u8 *)ID) + i + 1) << 8);
GB2312 = UnicodeToGB2312(tmp); //将对应的Unicode码转化为GB2312码
if(((GB2312 & 0xFF00) != 0) && ((GB2312 & 0xFF00) != 0xFF00))//去掉0和FF
filename[(*len)++] = (GB2312 & 0xFF00) >> 8;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -