📄 fat16.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 + -