📄 fat.c
字号:
//*************************************************************
#include "includes.h"
#include "UNICODE.h"
//*************************************************************
unsigned char System_ID; //系统ID(磁盘0扇区0x1c2)
//0x01、0x0b、0x0c为FAT32,0x04、0x06、0x0e为FAT16.
unsigned long Relative_Sectors; //相对扇区数(磁盘0扇区0x1c6)
unsigned long Total_Sector; //分区扇区总数(磁盘0扇区0x1ca)
//***************************************************************
unsigned int Bytes_Per_Sector; //每扇区字节数(分区0扇区0x0b)
unsigned char Sectors_Per_Cluster; //每簇扇区数(分区0扇区0x0d)
unsigned int Reserved_Sectors; //保留扇区数(分区0扇区0x0e)
unsigned char Number_Of_FATs; //FAT数(分区0扇区0x10)
unsigned int FAT16_Sectors_Per_FAT; //每FAT扇区数(分区0扇区0x16)
unsigned long FAT32_Sectors_Per_FAT;//每FAT扇区数(分区0扇区0x24)
unsigned long Root_Entries; //根目录入口()
unsigned long FAT_Head; //FAT表第一个簇
typedef struct
{
unsigned char Filename [8]; //文件名
unsigned char Extension[3]; //扩展名
unsigned char Attributes; //文件读写属性
unsigned long Cluster; //首簇号
unsigned long File_size; //文件大小
}File;
File File_Arry[40];
typedef struct
{
unsigned char NowSecter;
unsigned int NowFile;
}NowDir;
NowDir Dir[128];
unsigned long DirCluster;
unsigned char Deep;
unsigned char FileOpenMode;
unsigned char LNAdd[]=
{0x01,0x03,0x05,0x07,0x09,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E
};
unsigned int LongName[64];
unsigned char NextDir;
//***************************************************
//函数名称:Get_FAT_Basic_Info(void)
//函数功能:获取FAT文件系统的基本属性
//输入:无
//输出:0:成功 1:失败
//说明:先根据磁盘的0扇区读取分区的基本信息,再根据
// 基本信息读出分区的起始扇区,从而提取出分区的
// 各项属性
//***************************************************
unsigned char Get_FAT_Basic_Info(void)//
{
unsigned char temp;
//**************************************************
//获取分区信息
temp=Get_One_Sector_DATA(0);
System_ID=Sector_Buffer[0x1c2];
if(System_ID==0x01||System_ID==0x0b||System_ID==0x0c)System_ID=FAT32;
else if (System_ID==0x04||System_ID==0x06||System_ID==0x0e)System_ID=FAT16;
Relative_Sectors=*((unsigned long *)(Sector_Buffer+0x1C6));
Total_Sector=*((unsigned long *)(Sector_Buffer+0x1CA));
//*****************************************************
//获取FAT属性
temp=Get_One_Sector_DATA(Relative_Sectors);
Bytes_Per_Sector =*((unsigned int *)(Sector_Buffer+0x0B));
Sectors_Per_Cluster =Sector_Buffer[0x0D];
Reserved_Sectors =*((unsigned int *)(Sector_Buffer+0x0E));
Number_Of_FATs =Sector_Buffer[0x10];
if(System_ID==FAT16)//FAT16文件系统
FAT16_Sectors_Per_FAT =*((unsigned int *)(Sector_Buffer+0x16));
else if(System_ID==FAT32)//FAT32文件系统
FAT32_Sectors_Per_FAT =*((unsigned long *)(Sector_Buffer+0x24));
//根目录入口=相对扇区数+保留扇区数+FAT数×每FAT扇区数
FAT_Head =Relative_Sectors+Reserved_Sectors;
Root_Entries=FAT_Head+Number_Of_FATs*((System_ID==FAT16)?FAT16_Sectors_Per_FAT:FAT32_Sectors_Per_FAT);
return(0);
}
//***************************************************
//函数名称:Uincode_to_GB(unsigned int x)
//函数功能:将Unicode转换为GB
//输入:UNICODE编码
//输出:GB编码
//说明:函数内读到FLASH区数组时用到库pgm_read_word(地址);
//***************************************************
unsigned int Uincode_to_GB(unsigned int x)
{//UNICODE码转换为GB2313汉字编码
unsigned int a,b,c;
if((x >= 0x0020) && (x <= 0x007E))
{
//if(x >= 'a' && x <= 'z')
//x-='a'-'A';
//x+=0xA380;
return x;
}
if(x<pgm_read_word(&Unicode[0]))
{
x=0x3F3F;
return x;
}
if(x>pgm_read_word(&Unicode[UNICODE_MAX-1]))
{
x=0x3F3F;
return x;
}
a=0;
b=UNICODE_MAX-1;
do //采用二分查表法,因为该表为顺序表
{
c=(a+b)/2;
if(x==pgm_read_word(&Unicode[c]))
{
x=pgm_read_word((unsigned int *)(&Unicode[c])+1);
return x;
}
if(x<pgm_read_word(&Unicode[c]))
{
b=(a+b)/2;
}
else
{
a=(a+b+1)/2;
}
} while(a!=b);
if(x==pgm_read_word(&Unicode[a]))
{
x=pgm_read_word((unsigned int *)(&Unicode[a])+1);
return x;
}
x=0x3f3f; //如果找不到,则显示??
return x;
}
//***************************************************
//函数名称:
//函数功能:将Sector_Buffer缓冲区偏移temp的文件名从串口发送
//输入:
//输出:
//说明:Sector_Buffer缓冲区应为目录扇区,temp为32的整数倍
//***************************************************
void getfileinfo(unsigned int temp)
{
unsigned char i;
//从串口发送到电脑
UDR0=13;
while((UCSR0A&(1<<TXC0))==0);
UCSR0A|=(1<<TXC1);
UDR0=10;
while((UCSR0A&(1<<TXC0))==0);
UCSR0A|=(1<<TXC1);
for(i=0;i<11;i++)
{
UDR0=Sector_Buffer[temp+i];
while((UCSR0A&(1<<TXC0))==0);
UCSR0A|=(1<<TXC1);
}
}
//***************************************************
//函数名称:GetLongName(unsigned long SecterAdd,unsigned int MenuFile)
//函数功能:将文件的长文件名UNICODE码取出放在数组LongName里
//输入:SecterAdd:文件目录项所在扇区 MenuFile:目录项偏移地址
//输出:无
//说明:暂不支持多簇目录
//***************************************************
void GetLongName(unsigned long SecterAdd,unsigned int MenuFile)
{
unsigned char i,j;
j=0;
if(MenuFile==0)//如果当前目录项为扇区第一项,则读取上一扇区
{
MenuFile=480;
Get_One_Sector_DATA(--SecterAdd);
}
else MenuFile-=32;
while((Sector_Buffer[MenuFile]!=0xE5)&&(Sector_Buffer[MenuFile+0x0B]==0x0F))
{
for(i=0;i<13;i++)
{
LongName[j]=*((unsigned int *)(Sector_Buffer+MenuFile+LNAdd[i]));
if(LongName[j]==0)return;
j++;
}
if(Sector_Buffer[MenuFile]&0x40)
{
LongName[j]=0;
return;
}
if(MenuFile==0)//如果当前目录项为扇区第一项,则读取上一扇区
{
MenuFile=480;
Get_One_Sector_DATA(--SecterAdd);
}
else MenuFile-=32;
}
LongName[j]=0;
}
//***************************************************
//函数名称:SendLongName(void)
//函数功能:把数组LongName里的长文件名通过串口发送
//输入:无
//输出:无
//说明:LongName数组里面存放的是UNICODE编码,发送时先将其转换为GB编码
//***************************************************
void SendLongName(void)
{
unsigned char i;
unsigned int temp;
UDR0=13;
while((UCSR0A&(1<<TXC0))==0);
UCSR0A|=(1<<TXC1);
UDR0=10;
while((UCSR0A&(1<<TXC0))==0);
UCSR0A|=(1<<TXC1);
for(i=0;i<64&&LongName[i]!=0;i++)
{
temp=Uincode_to_GB(LongName[i]);
//temp=LongName[i];//直接发送UNICODE,在调试时用
if(temp>256)//过滤只有一字节的ASCII码
{
UDR0=(temp>>8);
while((UCSR0A&(1<<TXC0))==0);
UCSR0A|=(1<<TXC1);
}
UDR0=temp;
while((UCSR0A&(1<<TXC0))==0);
UCSR0A|=(1<<TXC1);
}
}
//***************************************************
//函数名称:Dir_Mp3(void)
//函数功能:查找目录下文件
//输入:无
//输出:无
//说明:将该目录下所有有效文件找出
//***************************************************
void Dir_Mp3(void)
{
unsigned char NowSecter,open;
unsigned int NowFile;
unsigned long File_Size,Start_Cluster,NowSecterAdd;
for(NowSecter=0;NowSecter<Sectors_Per_Cluster;NowSecter++)
{ for(NowFile=0;NowFile<512;NowFile+=32) //扫描扇区中的每个目录项
{
NowSecterAdd=(unsigned long)(Root_Entries+((System_ID==FAT16)?32:0)+(DirCluster-2)*Sectors_Per_Cluster+NowSecter);
Get_One_Sector_DATA(NowSecterAdd);//重新获取扇区的数据
if((Sector_Buffer[NowFile]!=0xE5)&&(Sector_Buffer[NowFile+0x0B]==0x20))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -