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

📄 fat16.c

📁 用89C51SND1C实现MP3播放器的源代码.用KEIL c51编写.
💻 C
字号:
/****************************************************************/
/*					UP-MP3DIY100								*/
/*		Beijing Universal Pioneering Technology Co., LTD		*/
/*		CopyRighted,All right Reserved	www.up-tech.com			*/
/*						July,2003								*/
/*				010-62387873  62381842							*/
/****************************************************************/

#include "Fat16.h"
#include "Flash.h"
#include "uart.h"
#include "string.h"

//数据结构与全局变量定义
extern unsigned char Page_Buf[];//外部变量申明,Page/扇区缓存
extern unsigned char SONG[];	//外部变量申明,歌曲列表数组

//读取MP3时的辅助变量
long int Current_Cluster,DataRead=0,DataRemain=0;

//文件系统有关变量申明
unsigned int TotalCluster,BootSector,RsdSector,SectorofFatSize,TotalCapacity,RootEntry,SecPerClus,TotalSector,BytesPerSec,FirstDataSec;
unsigned char FAT_TYPE;

//文件系统初始化,由存储体得到分区信息
void Init_FAT_Info(void)
{

	///////////////////////////////////////////////////
	//得到引导扇区所在扇区号,如果介质是不带分区的,则0扇区就是BootSector了。
	ReadPage(Begin_Cluster,0,Page_Buf);

	if(!(Page_Buf[0]==0xeb&&Page_Buf[2]==0x90)){	//通过判断EB ?? 90来看是否已经是BPB了
		//带分区的介质
		BootSector=Page_Buf[454]+Page_Buf[455]*256+Page_Buf[456]*(256*256)+Page_Buf[457]*(256*256*256);
		}
	else BootSector=0;
	///////////////////////////////////////////////////

	////////////////////////////////////////////////
	//得到保留扇区数,总扇区数,总扇区数/每簇扇区数得到簇数,是FAT类型的依据
	ReadPage(Begin_Cluster,BootSector,Page_Buf);
	RsdSector=Page_Buf[14]+Page_Buf[15]*256;//得到保留扇区数
	SecPerClus=Page_Buf[13];//得到每簇扇区数

	BytesPerSec=Page_Buf[12]*256+Page_Buf[11];//得到每扇区字节数

	TotalSector=(Page_Buf[20]*256+Page_Buf[19]);//得到总扇区数
	TotalCapacity=TotalSector*BytesPerSec;//得到总容量
	TotalCluster=TotalSector/SecPerClus;//FAT16的簇总数=扇区总数/每簇扇区数

	SectorofFatSize=((Page_Buf[22]+Page_Buf[23]*256));//得到每个分区表的扇区数
	RootEntry=(Page_Buf[18]*256+Page_Buf[17]);//得根目录项数
	//得第一个存放数据的扇区的位置
	FirstDataSec=BootSector+RsdSector+(SectorofFatSize*2)+((RootEntry*32+(BytesPerSec-1))/BytesPerSec);

	if(TotalCluster>65525){  //如果此分区为FAT32,则以下代码决定FAT32的扇区总数和FAT表项长度
		FAT_TYPE=FAT32;

		if(TotalSector==0) TotalSector=(Page_Buf[32]+Page_Buf[33]*256+Page_Buf[34]*256*256+Page_Buf[35]*256*256*256);
		TotalCapacity=TotalSector*BytesPerSec;
		TotalCluster=TotalSector/SecPerClus;

		SectorofFatSize=(Page_Buf[36]+Page_Buf[37]*256+Page_Buf[38]*256*256+Page_Buf[39]*256*256*256);
		if(SectorofFatSize>(TotalCluster*16/512)) SectorofFatSize=((Page_Buf[22]+Page_Buf[23]*256));
		RootEntry=(Page_Buf[44]*256+Page_Buf[43]);
		FirstDataSec=BootSector+RsdSector+(SectorofFatSize*2)+((RootEntry*32+(BytesPerSec-1))/BytesPerSec);
		
		}
	else if((TotalCluster>0)&&(TotalCluster<4085)) {//根据簇的数量决定FAT分区表的类型,FAT12
		FAT_TYPE=FAT12;
		}
	else {	//FAT16
		FAT_TYPE=FAT16;
		}
	
}

//生成MP3歌曲列表
unsigned char GetMP3List(void)
{
	unsigned char i=0,j=0,l=0;
	int k=0;
	unsigned char MP3[3]={'M','P','3'};
	Init_FAT_Info();//初始化文件系统

	k=BootSector+RsdSector+2*SectorofFatSize;
//	printuf("BootSector:%x",BootSector);
//	printuf("RsdSector:%x",RsdSector);
//	printuf("SectorofFatSize:%x",SectorofFatSize);
//	printuf("RootDIR:%x",(k&0xff00)>>8);
//	printuf("%x\n",k);

	ReadPage(0+k/32,k%32,Page_Buf);//读根目录区的首页

	while(Page_Buf[0]!=0){//遍历整个目录
		for(j=0;j<16;j++){//每个扇区为512字节,可容纳16个根目录项,每个根目录项32字节
				if(!Page_Buf[j*32]) break;//如果到达根目录的最后,则结束搜索
				if(Page_Buf[j*32]==0xE5) continue;//如果某个文件项是已经被删除了的,则转向下一文件项

				if(!memcmp(MP3,&Page_Buf[j*32+8],3)){	//找到一个扩展名为MP3的文件,file find
					for(i=0;i<11;i++) SONG[l*11+i]=Page_Buf[j*32+i];//将其文件名复制到MP3歌曲列表中
					l++;//歌曲总数计数加1
					}
				}
		k++;//指向根目录表的下一个扇区
		ReadPage(0+k/32,k%32,Page_Buf);//读取下一个扇区的根目录表项数据
		}
	return(l);//返回找到的MP3歌曲的总数
}

//从当前MP3歌曲中读取512个字节
int ReadSector(unsigned char *Name,unsigned char *databuff)
{
	int i,k,Page;
	if(DataRead==0) //第一次读取,先查找文件,然后进行读取
		{
			Page=BootSector+RsdSector+2*SectorofFatSize;
			ReadPage(0+Page/32,Page%32,databuff);//读取根目录项
			while(databuff[0]!=0){//遍历整个目录
			for(i=0;i<16;i++){
							if(!memcmp(Name,&databuff[i*32],11)){//找到要播放的那个文件
								Current_Cluster=databuff[32*i+27]*256+databuff[32*i+26];//得当前文件的首簇
								printuf("Current_Cluster:%x",(Current_Cluster&0xff00)>>8);
								printuf("%x\n",Current_Cluster);
								for(k=31;k>27;k--) DataRemain=(DataRemain<<8)|databuff[i*32+k];//得文件长度
								ReadPage((Current_Cluster+0x11d)/32,(Current_Cluster+0x11d)%32,databuff);//读取512个字节

								DataRead+=512;//已读字节数加512
								DataRemain-=512;//剩余字节数减512
								if(DataRemain<0) {DataRead=0;return(DataRemain+512);}//如果数据已全部读完,则返回实际本次读取的有效字节数
								else return(512);//若未读完此歌曲,则返回512
							}
						}
				Page++;//指向根目录区的下一个扇区
				ReadPage(0+Page/32,Page%32,databuff);//读取根目录区的此扇区内容
		  }
		  printu("\nfile is not found!");return(0);
		}
	else
		{
//			if((Current_Cluster+0x11d+DataRead/BytesPerSec)%32) Current_Cluster=NextCluster(Current_Cluster);
			ReadPage((Current_Cluster+0x11d)/32,(Current_Cluster+0x11d+DataRead/BytesPerSec)%32,databuff);//继续读取下一扇区
			DataRead+=512;//已读字节数加512
//			if(!((Current_Cluster+0x11d+DataRead/BytesPerSec)%32)) Current_Cluster=NextCluster(Current_Cluster+32);//指向此歌曲文件的下一个簇
			if(!((Current_Cluster+0x11d+DataRead/BytesPerSec)%32)) Current_Cluster+=32;//指向下一个Block,默认歌曲文件是顺序存放的。
			DataRemain-=512;//剩余字节数减512
			if(DataRemain<0) {DataRead=0;return(DataRemain+512);}//返回本次读取的字节数
			else return(512);
			}

}

//此部分代码获取MP3歌曲文件的下一个簇,但由于受处理速度的影响,当每读一个512字节的音乐数据时,都要先读一下文件分配表,这
//将大大增加处理器的负担,按这种方式处理时,MP3音乐文件会不连续.因此,这里默认MP3文件是顺序存放的,不读取文件分配表,得到
//文件的首簇位置后,便一直往下读,直到读满文件长度那么多数据为至,这种方式解决了速度问题,但有可能存在问题.
//这个问题的存在,是由于U盘与MP3兼容,且不需要驱动而带来的.
/*
unsigned int NextCluster(unsigned int CurrentCluster)
{
	unsigned int i,j;
	if(FAT_TYPE==FAT12){
		ReadPage(Begin_Cluster+(BootSector+RsdSector+(CurrentCluster*3/2)/BytesPerSec)/SecPerClus,(BootSector+RsdSector+(CurrentCluster*3/2)/BytesPerSec)%SecPerClus,Page_Buf);
		if(CurrentCluster%2==0) {
			j=Page_Buf[(CurrentCluster*3/2)%BytesPerSec+1];
			i=Page_Buf[(CurrentCluster*3/2)%BytesPerSec]|(j<<8);
			i&=0x0fff;
			}
		else {
			j=Page_Buf[(CurrentCluster*3/2)%BytesPerSec+1];
			i=Page_Buf[(CurrentCluster*3/2)%BytesPerSec]|(j<<8);
			i=(i>>4);
			}
		return (i);
		}
	else if(FAT_TYPE==FAT16){
		ReadPage(Begin_Cluster+(BootSector+RsdSector+(CurrentCluster*2)/BytesPerSec)/32,(BootSector+RsdSector+(CurrentCluster*2)/BytesPerSec)%32,Page_Buf);
		i=Page_Buf[(CurrentCluster*2)%BytesPerSec+1]*256+Page_Buf[(CurrentCluster*2)%BytesPerSec];
		return (i);
		}
	else if(FAT_TYPE==FAT32){
		ReadPage(Begin_Cluster+(BootSector+RsdSector+(CurrentCluster*4)/BytesPerSec)/SecPerClus,(BootSector+RsdSector+(CurrentCluster*4)/BytesPerSec)%SecPerClus,Page_Buf);
		i=Page_Buf[(CurrentCluster*4)%BytesPerSec+3]*256*256*256+Page_Buf[(CurrentCluster*4)%BytesPerSec+2]*256*256+Page_Buf[(CurrentCluster*4)%BytesPerSec+1]*256+Page_Buf[(CurrentCluster*4)%BytesPerSec];
		return (i);
		}
}
*/



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -