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

📄 fat16.c

📁 AVR单片机做的MP3
💻 C
字号:
#include<iom16v.h>
#include<main.h>
#include<fat16.h>
#include<12232.h>
#include<sd.h>
#include<vs1003.h>
extern uint8 BUFFER[512];
extern zikustart;
static uint16 unicodestart;
static uint16 vol=0x0a0a;
static uint16 fileindex=0;
static DIR fileid;
static uint8 flag=1;
static uint8 keyflag=0;
static uint8 longfileflag=0;
static uint8 volume[2]="50";
volatile static uint8  timecount=0;

unsigned char zero[32]={0};
typedef struct
{
	uint16 m;
	uint16 ClusID;
	uint32 i;
	uint32 LBA;
} FATFileIndex;
static FATFileIndex    FileIndex;        //当前打开的文件
uint8                  BPB_SecPerClus;
static uint16          BPB_RsvdSecCnt;
static uint8           BPB_NumFATs;
static uint16          BPB_RootEntCnt;
static uint16          BPB_TotSec16;
static uint16          BPB_FATSz16;
static uint32          BPB_HiddSec;

void     ReadBlock        (uint32 LBA);
void     WriteBlock       (uint32 LBA);
static   uint8    IsEqual          (void* A, void* B, uint8 Size);
static uint8 Ismp3(void* A);
void     ReadBPB          (void);
static uint32   ClusConvLBA      (uint16 ClusID);
uint16   ReadFAT          (uint16 Index);
static uint16    GetNextmp3(void);
static uint8 GetFileID(uint8 Name[11],DIR* ID);
void show(uint8 filename[2],uint8 location,uint8 loca);

void FAT_Init(void)
{
	ReadBPB();
}

void SD_SPI_HIGH(void)
{
   SPCR=(1<<SPE)|(1<<MSTR);
   SPSR|= (1<<SPI2X);
}
//********************************************************************************************
//读一个扇区
void ReadBlock(uint32 LBA)
//********************************************************************************************
{
	SD_read_sector(LBA, BUFFER);
}

//********************************************************************************************
void WriteBlock(uint32 LBA)
//********************************************************************************************
{
	SD_write_sector(LBA , BUFFER);
}

//********************************************************************************************
static uint8 IsEqual(void* A, void* B, uint8 Size)
//********************************************************************************************
{
	uint8 i, *a = A, *b = B;
	for(i = 0; i < Size; i++)
	{
		if((a[i] != b[i]))
			return 0;
	}
	return 1;
}
static uint8 Ismp3(void* A)
{
 uint8 i,*a=A;
 uint8 b[3]="MP3";
 uint8 c[3]="WMA";
 if((a[0]==0xe5)||(a[0]==0)) return 0;
 for(i=0;i<3;i++)
 {
  if((a[i+8]!=b[i])&&(a[i+8]!=c[i]))
     return 0;
 }
  return 1;

}
//********************************************************************************************
//读取BPB数据结构
void ReadBPB(void)
//********************************************************************************************
{
	FAT_BPB* BPB = (FAT_BPB*)BUFFER;
	ReadBlock(0);

	//缓存相关参数
	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;

}

//********************************************************************************************
//获取根目录开始扇区号
static uint32 DirStartSec(void)
//********************************************************************************************
{
	return BPB_RsvdSecCnt + BPB_NumFATs * BPB_FATSz16;
}

//********************************************************************************************
//获取数据区开始扇区号
static uint32 DataStartSec(void)
//********************************************************************************************
{
	return DirStartSec() +( BPB_RootEntCnt >>4);
} 

//********************************************************************************************
//目录项占用的扇区数
static uint16 GetDirSecCount(void)
//********************************************************************************************
{
	return (BPB_RootEntCnt >>4);
}

//********************************************************************************************
//获取一个簇的开始扇区
uint32 ClusConvLBA(uint16 ClusID)
//********************************************************************************************
{
    return DataStartSec() + ((uint32)BPB_SecPerClus) * (ClusID - 2); 
}

//********************************************************************************************
//读取文件分配表的指定项
static uint16 ReadFAT(uint16 Index)
//********************************************************************************************
{
	uint16 *RAM = (uint16*)BUFFER;
	ReadBlock(BPB_RsvdSecCnt + (Index >>8));
	return RAM[Index % 256];
}

uint16 GetNextmp3()
{
    uint16 DirSecCut, DirStart;
	uint8 i,m;
	DirSecCut = GetDirSecCount();
    while(fileindex<=512)
    {
	  if(flag) fileindex++;
	  else     fileindex--;
	  if(fileindex<=1) fileindex=510;
	  if(fileindex>=511)fileindex=2;
	  i=fileindex/16;
	  DirStart = DirStartSec();
	  ReadBlock(DirStart + i);
	  m=(fileindex%16);
	  if(Ismp3(&((DIR*)&BUFFER[m * 32])->FileName))
	   {
		*(&fileid) = *((DIR*)&BUFFER[m * 32]);
		return 1; //找到对应的目录项,返回位置
	   }
    }
}
static uint8 GetFileID(uint8 Name[11],DIR* ID)
//********************************************************************************************
{
	uint16 DirSecCut, DirStart, i, m;
	DirSecCut = GetDirSecCount();
	DirStart = DirStartSec();
	for(i = 0; i < DirSecCut; i++)
	{
		ReadBlock(DirStart + i);
		for(m = 0; m <16; m++)
		{
			if(IsEqual(Name, &((DIR*)&BUFFER[m * 32])->FileName, 11))
			{
				*ID = *((DIR*)&BUFFER[m * 32]);
				return 1; //找到对应的目录项,返回1
			}
		}
	}
	return 0; //没有找到对应的目录项,返回0
}
static uint8 Readfile()
{
  static uint16 r,t,p,pointer=0,m;
  static uint8 filename[11],i,j=0;
  uint8 unicodename[16];
  uint16 BytePerClus, ClusNum,NextClus,count=0,DirStart;
  uint32 LBA,lenth;
  if(fileid.FileName[7]==0x31) 
  {
   t=0;
   longfileflag=1;
   count=fileindex-1;
   m=count%16;
   m<<=5;
   for(i=0;i<16;i++)
   {
    if(i<10)unicodename[i]=BUFFER[m+i+1];
	else  unicodename[i]=BUFFER[m+i+4]; 
    if((BUFFER[m+1+i]==0x2E)&&(BUFFER[m+2+i]==0))
	{
	 while(i<16)
	 {
	 unicodename[i++]=0;
	 }
	 break;
	}
   }
    for(i=0;i<16;i+=2)
   {
    if(i<8)
	{
    show(unicodename+i,(uint8)t,0);
	}
	else
	{
	show(unicodename+i,(uint8)t-60,1);
	}
    t+=15;
   }
  }
  else                        
   {
   t=0;
   longfileflag=0;
   for(r=0;r<16;r+=2)
   {
    if(r<8)show(fileid.FileName+r,(uint8)t,0);
	else show(zero,(uint8)t-60,1);
    t+=15;
   }
   }
 FileIndex.ClusID=fileid.FilePosit.Start;
 LBA=ClusConvLBA(FileIndex.ClusID);
 lenth=fileid.FilePosit.Size;
 
 BytePerClus=BPB_SecPerClus * 512;
 ClusNum=lenth/BytePerClus+1;
 NextClus=FileIndex.ClusID;
 for(t=0;t<ClusNum;t++)
 {
 for(r=0;r<BPB_SecPerClus;r++)
  {
  SD_SPI_HIGH();
  ReadBlock(LBA+r);
  while(pointer<512)
   {
   if(PINB&1)
    {
     for(p=0;p<32;p++)
     {
     VS1003B_WriteDAT(BUFFER[pointer]);
     pointer++;
     }
	 if(pointer==511) break;
    }
	//按键处理
     if(!(PINA&NEXT)) 
     {
	  delay(10);
	  if(!(PINA&NEXT)) 
	  {  
	  lcd_on();
	  keyflag=1;
	  flag=1;
	  VS1003B_SoftReset();
      return 5;
	  }
	 }
	 if(!(PINC&PREV))
	 {
	  delay(10);
	  if(!(PINC&PREV))
	  {
	  lcd_on();
	  keyflag=1;
	  flag=0;
	  VS1003B_SoftReset();
	  return 6;
	  }
	 }
	 if(!(PINA&PLAY))
	 {
	  delay(600);
	  lcd_on();
	  while(PINA&PLAY);
	  keyflag=1;
	  delay(600);
	 }
   }
   pointer=0;
  }
  if(!(PINA&UP))
	 {
	  if(!(PINA&UP))
	  {
	  lcd_on();
	  keyflag=1;
	  longfileflag=0;
	  vol=vol-((uint16)(4<<8)+4); 
	  volume[0]++; 
	  if(volume[0]>0x36)
	  {
	  vol=0x0505;
	  volume[0]=0x36;
	  }
      else
	  {
	  VS1003B_WriteCMD(0x0b,vol);  //每次左右声道VOL+2 
	  }
	  show(volume,108,0);
	  }
	 }
	 if(!(PINA&DOWN))
	 {
	  if(!(PINA&DOWN))
	  {
	  lcd_on();
	  keyflag=1;
	  longfileflag=0;
	  vol=vol+((uint16)(4<<8)+4);
	  volume[0]--; 
	  if(volume[0]<0x30)
	  {
	   vol=0x1d1d;
	   volume[0]=0x30;
	   }
      else 
	  {
	  VS1003B_WriteCMD(0x0b,vol);//每次左右声道VOL-4
	  }
	  show(volume,108,0);
	  }
	 }
  pointer=0;
  if(NextClus>=0xfff8) break;
  if(t==20)  lcd_off();
  if(keyflag)
  {
   j++;
   if(j>20) 
    {
	 lcd_off();
	 j=0;
	 keyflag=0;
	}
  }
  NextClus=ReadFAT(NextClus);
  LBA=ClusConvLBA(NextClus);
 }
 return 1;
}
uint16 Getfile_start()
{
 uint16 i;
 DIR zikudir;
 uint8 ziku[11]="ZIKU16  DAT";
 uint8 unicode[11]="UNICODE DAT";
 if(flag)  
 {
  i=GetFileID(ziku,&zikudir);
  flag=0;
  }
 else     
 {
  i=GetFileID(unicode,&zikudir);
 }
 if(!i) 
 {
  return 0;
 }
 i=zikudir.FilePosit.Start;
 return i;
}
void show( uint8 filename[2],uint8 location,uint8 loca)
{
 uint16 i,j=0;
 uint8 x,y,location1,loca1,findflag=0;
 uint32 temp,temp1,temp2,start;
 x=filename[0];
 y=filename[1];
 location1=location;
 loca1=loca;
 if(!longfileflag)
 {
 if((x<0xb0))
 {
  if((x>=0x30)&&(x<0x61))
  {
  y=128+x;
  x=163;
  }
  else
  {
  show_chin(zero,location,1,loca);
  return;
  }
 }
 x=x-0xa1;
 y=y-0xa1;
 temp=x*94;
 temp=temp+y;
 }
 else
 {
 start=ClusConvLBA(unicodestart);
 for(i=0;i<16;i++)
  {
   ReadBlock(start+i);
   for(j=0;j<512;j+=2)
     {
      if((x==BUFFER[j])&&(y==BUFFER[j+1]))
	   {
	     findflag=1;
	     temp=i<<8;
		 temp=temp+(j>>1);
		 temp=temp+1410;
		 break;
	   }
	 }
  
  if(findflag)  
   {
    break;
   }
 if((!findflag)&&(i==15))
   {
   show_chin(zero,location1,1,loca1);
   return;
   }
  }
 }
 temp=temp<<5;
 temp1=temp>>9;
 temp2=temp%512;
 start=ClusConvLBA(zikustart);
 start=start+temp1;
 ReadBlock(start);
 show_chin(BUFFER+(uint16)(temp2),location1,1,loca1);
}
void playmp3(void)
{
 uint16 song=0;
 uint8 test2[6]="音量50";
 uint8 welcome[8]="欢迎使用";
 uint8 mp3[6]="M0P030"; 
 zikustart=Getfile_start();
 show(welcome,0,0);
  show(welcome+2,15,0);
   show(welcome+4,30,0);
    show(welcome+6,45,0);
 show(test2,76,0);
  show(test2+2,92,0);
   show(test2+4,108,0);
    show(mp3,76,1);
 show(mp3+2,91,1);
 show(mp3+4,106,1);
 delay(3000);
 unicodestart=Getfile_start();
 while(1)
 {
 song=GetNextmp3();
 Readfile();
 VS1003B_SoftReset();
 delay(500);
 }
}

⌨️ 快捷键说明

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