音乐播放器的两个关键点:1、用FATFS对音乐文件进行管理,包括打开,读取等。2、配置Codec芯片,通过DMA,把读取的音乐文件数据送到Codec。
这个工程中,主要实现第一个大点的一些操作。
直接上程序,需要注意的几个点。
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "lcd.h" #include "key.h" #include "sram.h" #include "malloc.h" #include "sdio_sdcard.h" #include "malloc.h" #include "ff.h" #include "string.h" #include "fattester.h"void upper(char *p); //这个函数用来把小写字母转换成大写 u8 tell_type(char *p); //通过后缀名识别文件类型 u8 wav_decode(FIL *p); //WAV文件的解码 u8 *readbuf; UINT mybr; int main(void) { u8 key,res,music_number; char *myfn; char *myfn_temp; char *filename_temp;
//FATFS相关的变量 FATFS *fs[1]; FIL *myfile; DIR mydir; FILINFO myfileinfo; FRESULT myres; //初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); delay_init(168); uart_init(115200); LED_Init(); KEY_Init(); my_mem_init(SRAMIN); my_mem_init(SRAMCCM); //SD卡初始化 while(SD_Init()) { delay_ms(500); LED0=!LED0; } //FATFS相关的很多函数,用到的结构体,需要申请内存,不然会出错,比如f_mount/f_open fs[0]=(FATFS*)mymalloc(SRAMIN,sizeof(FATFS)); myfile=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); myfileinfo.lfsize = _MAX_LFN * 2 + 1; myfileinfo.lfname = mymalloc(SRAMIN,myfileinfo.lfsize); // 支持长文件名,方法为3,需要动态申请内存 _USE_LFN=3 readbuf=(u8*)mymalloc(SRAMIN,512); //读文件的缓冲区 myfn_temp= (char *)mymalloc(SRAMIN,myfileinfo.lfsize); res=f_mount(fs[0],"0:",1); //挂载 while(1) { key=KEY_Scan(0); if(key==1) //测试当前目录的文件读取,f_open-----f_read { f_open(myfile,"test1.txt",FA_READ); res=f_read(myfile,readbuf,20,&mybr); if(res) printf("Read Error:%d\r\n",res); else while(*readbuf!='\0') { printf("%c",*readbuf); readbuf++; } } if(key==2) //文件类型识别 { music_number=0; f_opendir(&mydir,"0:/MUSIC"); // while(1) { myres=f_readdir(&mydir,&myfileinfo); //循环读取文件夹中所有的文件 if(myres != FR_OK || myfileinfo.fname[0] == 0) break; myfn = *myfileinfo.lfname ? myfileinfo.lfname : myfileinfo.fname; printf("\r\nFile name is %s\r\n",myfn); filename_temp=myfn; res=tell_type(myfn); if(res==0) { printf("This is a music file.\r\n"); music_number++;//strcat(myfn_temp,myfn); strcpy((char*)myfn_temp,"0:/MUSIC/"); strcat((char*)myfn_temp,(const char*)myfn); //获取文件的绝对路径 printf("\r\nFile name is %s\r\n",myfn_temp); f_open(myfile,myfn_temp,FA_READ); wav_decode(myfile); } } printf("\r\nThere is %d music file\r\n",music_number); } if(key==3) // { f_opendir(&mydir,"0:/MUSIC"); f_open(myfile,"0:/MUSIC/µË×ÏÆå-Äã°ÑÎÒ¹à×í.wav",FA_READ); wav_decode(myfile); } } } //把字符串中的大写改成小写 void upper(char *p) { while(*p!='\0') { if((*p>=97)&&(*p<=120)) *p=*p-32; p++; } } //通过后缀名识别文件类型 u8 tell_type(char *p) { int i=0; char *attr; while(i<200) { if(*p=='\0') break; i++; p++; } if(i==200) return 1; i=0; while(i<5) { if(*p=='.') { p++; attr=p; break; } i++; p--; } if(i==5) return 2; if((strcmp(attr,"WAV")==0)||(strcmp(attr,"wav")==0)) { return 0; } else { return 4; } } //RIFF¿é typedef __packed struct { u32 ChunkID; // 0X46464952 u32 ChunkSize ; u32 Format; }ChunkRIFF ; //fmt¿é typedef __packed struct { u32 ChunkID; u32 ChunkSize ; u16 AudioFormat; u16 NumOfChannels; u32 SampleRate; u32 ByteRate; u16 BlockAlign; u16 BitsPerSample; // u16 ByteExtraData; }ChunkFMT; //fact¿é typedef __packed struct { u32 ChunkID; u32 ChunkSize ; u32 NumOfSamples; }ChunkFACT; u8 wav_decode(FIL *p) { u8 res; ChunkRIFF *riff; ChunkFMT *fmt; res=f_read(p,readbuf,512,&mybr); //ÔÚÍâÃæÖÐÒѾopen if(res==FR_OK) { riff=(ChunkRIFF *)readbuf; printf("This is RIFF Chunk Read-----------\r\n"); printf("RIFF ChunkID is %x\r\n",riff->ChunkID); printf("RIFF ChunkSize is %d MB\r\n",riff->ChunkSize>>20); printf("RIFF Format is %x\r\n",riff->Format); printf("This is FMT Chunk Read-----------\r\n"); fmt=(ChunkFMT *)(readbuf+12); printf("FMT ChunkID is %x\r\n",fmt->ChunkID); printf("FMT ChunkSize is %d\r\n",fmt->ChunkSize); printf("FMT Channle is %d\r\n",fmt->NumOfChannels); } else { printf("Read Err:%d\r\n",res); } return res; }