⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 一个基于ATmega64、VS1003、SD卡的mp3播放程序
💻 C
📖 第 1 页 / 共 2 页
字号:
//*************************************************************
#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 + -