LPC1768 MP3录音和循环播放源码
2019-11-30 来源:51hei
LPC1768
2个程序,一个实现录音 一个实现循环播放
** 实验名:MP3
** KEIL MDK-ARM Standard Version:4.6
** 使用外设: 3.2寸LCD
**********************************************************************************/
/**********************************************************************************
测试说明:
此程序为MP3测试例程将MP3文件拷入到2G内存卡后,插上3.2寸液晶屏,插入耳机,下载程
序上电,开始播放歌曲并且在液晶屏上显示MP3文件名称(这里并不支持中文显示),调节
滑动变阻器可以改变播放声音
***********************************
单片机源程序如下:
/*******************************************************************************
* Company: Wang Electronic Technology Co., Ltd.
******************************************************************************
* 文件名称:main.c
* 功能说明:mp3播放
* 版 本:V1.1
* 作 者:jeansonm
* 日 期:2014-4-22
********************************************************************************
* 文件名称:
* 功能说明:
* 版 本:
* 更新作者:
* 日 期:
* 更新原因:
********************************************************************************/
#include #include 'LCD.h' #include 'string.h' #include 'sys.h' #include 'lcd.h' #include 'ff.h' #include 'config.h' #include 'vs1003.h' #include 'mp3.h' #include 'MMC_SD.h' #include 'delay.h' #include 'ssp0.h' #include 'adc.h' u8 MusicNumber; u8 temp; u8 count=0; u32 datasize=0; FATFS fs; // Work area (file system object) for logical drive FIL fsrc, fdst,fap,file; // file objects FRESULT res,re; // FatFs function common result code UINT br, bw,bt;; // File R/W count FILINFO finfo,fno; DIR dirs; u8 buffer[1024]; // file copy buffer u8 flag=0; void ReFresh(u8 *p) { LCD_Clear(Black); //清屏 LCD_DisplayString(60,30,'www#openmcu#com'); LCD_DisplayString(60,50,'bbs.openmcu.com'); LCD_DisplayString(60,70,'MP3 Test'); LCD_DisplayString(60,90,'Play:'); LCD_DisplayString(100,90,p); } /***************************************************************************** ** Main Function main() ******************************************************************************/ int main (void) { u8 i; u16 AD_value,AD_Old_value; SystemInit(); Vs1003_Init(); //vs1003引脚初始化 Vs1003SoftReset(); //vs1003软件复位 LCD_Init(); //LCD初始化 LCD_SetTextColor(Red);//设置字体为红色 LCD_SetBackColor(Black); //设置背景色为黑色 ReFresh(''); //刷新屏幕 USER_ADC_Init(); SD_Init(); //初始化SD卡 f_mount(0,&fs); //挂载文件系统 temp= FindMusic(); //音乐查找 MusicNumber=temp; bw = f_open(&fsrc,filename[0],FA_OPEN_EXISTING | FA_READ); //打开第一个文件 ReFresh((u8 *)(filename[0])); // VsSineTest(); //正弦波测试 ,会听到滴答声 ,说明VS1003 初始化通过 while(1) { if(datasize>=fsrc.fsize) //到达文件尾播放完成 flag=1; if(count++==10) { count=0; AD_value=USER_ADC_Get(); //获取AD转换值 if(abs(AD_value-AD_Old_value)>30) { AD_Old_value = AD_value; AD_value=((AD_value*255)/4096); AD_value<<=8; AD_value+=((AD_Old_value*255)/4096); Vs1003_CMD_Write(SPI_VOL,AD_value); //设音量 高八位为左声道 第八位为右声道,这里相同 } } if(flag==1) //文件播放完了 { flag=0; if(MusicNumber--) //下一个文件 { if(MusicNumber==0) //所有文件播放完了 { MusicNumber=temp; //从头开始播放 } bw = f_open(&fsrc,filename[temp-MusicNumber],FA_OPEN_EXISTING | FA_READ); ReFresh((u8 *)filename[temp-MusicNumber]); //更新显示 …………………… ** 实验名:MP3录音 ** KEIL MDK-ARM Standard Version: ** 使用外设: 3.2寸LCD mic头 耳机 **********************************************************************************/ /********************************************************************************** 测试说明: 此程序为VS1003 MP3播放录音测试例程,将1.mp3文件拷入到2G SD卡根目录下面,将SD卡 插在开发板上面,插上3.2寸彩屏模块,下载程序到开发板,彩屏显示按键功能信息, SD卡初始化成功后彩屏显示对应信息,按下INT0键开始录音,按下Key1键结束录音并播放录音 文件,按下Key2键播放1.mp3文件 注意:这里录音使用外接麦克风,开发板默认没有配置该麦克风,需要用户另行购买焊接。 /******************************************************************************* * Company: Wang Electronic Technology Co., Ltd. ****************************************************************************** * 文件名称:main.c * 功能说明:mp3播放录音 * 版 本:V1.1 * 作 者:jeansonm * 日 期:2014-4-26 ******************************************************************************** * 文件名称: * 功能说明: * 版 本: * 更新作者: * 日 期: * 更新原因: ********************************************************************************/ #include #include 'LCD.h' #include 'string.h' #include 'sys.h' #include 'lcd.h' #include 'ff.h' #include 'config.h' #include 'vs1003.h' #include 'mp3.h' #include 'MMC_SD.h' #include 'delay.h' #include 'ssp0.h' #include 'adc.h' u8 MusicNumber; u8 temp; u8 count=0; u32 datasize=0; FATFS fs; // Work area (file system object) for logical drive FIL fsrc, fdst,fap,file; // file objects FRESULT res,re; // FatFs function common result code UINT br, bw,bt;; // File R/W count FILINFO finfo,fno; DIR dirs; u8 buffer[1024]; // file copy buffer u8 flag=0; uint8_t wav_dat[512]={0}; static u8 status=0; /** first part of RIFF Header, insert 444 zeroes after this */ unsigned char RIFFHeader0[52] = {'R' , 'I' , 'F' , 'F' , //资源交换文件标志(RIFF) 0x70, 0x70, 0x70, 0x70, //从下一个地址开始到文件尾总字节数 (calculate after rec!) 'W' , 'A' , 'V' , 'E' , //wav文件格式 'f' , 'm' , 't' , ' ' , //波形格式标志(fmt ) 0x14, 0x00, 0x00, 0x00, //量化结果 (0x14 = 20 bytes) 0x11, 0x00, // 有无压缩编码 (IMA ADPCM) 0x01, 0x00, // 通道数 单声道 (1) 0x40, 0x1f, 0x00, 0x00, //采样频率, 0x1f40 = 8.0kHz 0xd7, 0x0f, 0x00, 0x00, //比特率 0x00, 0x01, //块数据大小(256 bytes) 0x04, 0x00, //样本数据位数(4 bits) 0x02, 0x00, // Extra data (2 bytes) 0xf9, 0x01, // Samples per Block (505 samples) 'f' , 'a' , 'c' , 't' , // Chunk ID (fact) 0xc8, 0x01, 0x00, 0x00, // Chunk payload size (456 bytes (zeropad!)) 0xff, 0xff, 0xff, 0xff // Number of Samples (calculate after rec!) }; // Insert 448 zeroes here! //add 452 zeros after unsigned char RIFFHeader504[8] = {'d' , 'a' , 't' , 'a' , // Chunk ID (data) 0x70, 0x70, 0x70, 0x70 // Chunk payload size (calculate after rec!) }; /********************************************************************************************************* ** Function name: ReFresh ** Descriptions: 屏幕更新 ** input parameters: p 显示信息字符串 ** output parameters: 无 ** Returned value: 无 *********************************************************************************************************/ void ReFresh(u8 *p) { LCD_Clear(Black); //清屏 LCD_DisplayString(60,30,'WB-Beemer Record'); LCD_DisplayString(60,50,'INT0:Start Record'); LCD_DisplayString(60,70,'Key1:Save & Paly'); LCD_DisplayString(60,90,'Key2:Paly 1.mp3'); LCD_DisplayString(60,110,p); } /********************************************************************************************************* ** Function name: BUTTON_init ** Descriptions: 按键初始化 ** input parameters: 无 ** output parameters: 无 ** Returned value: 无 *********************************************************************************************************/ void BUTTON_init(void) { LPC_GPIO2->FIODIR &= ~(1 << 10); //初始化端口P2.10为输入 LPC_GPIOINT->IO2IntEnF |= (1 << 10); //使能下降沿中断 LPC_GPIO2->FIODIR &= ~(1 << 11); //初始化端口P2.10为输入 LPC_GPIOINT->IO2IntEnF |= (1 << 11); //使能下降沿中断 LPC_GPIO2->FIODIR &= ~(1 << 12); //初始化端口P2.10为输入 LPC_GPIOINT->IO2IntEnF |= (1 << 12); //使能下降沿中断 NVIC_EnableIRQ(EINT3_IRQn); //利用IO口来做中断,这种与EINT3通道相同 } /********************************************************************************************************* ** Function name: EINT3_IRQHandler ** Descriptions: 外部中断函数 ** input parameters: 无 ** output parameters: 无 ** Returned value: 无 *********************************************************************************************************/ void EINT3_IRQHandler() { u32 Int_status=0; Int_status=LPC_GPIOINT->IO2IntStatF; if(Int_status & (1<<10)) { LPC_GPIOINT->IO2IntClr |= (1 << 10); //清除中断标志位 status=1; } else if(Int_status & (1<<11)) { LPC_GPIOINT->IO2IntClr |= (1 << 11); //清除中断标志位 status=2; } else if(Int_status & (1<<12)) { LPC_GPIOINT->IO2IntClr |= (1 << 12); //清除中断标志位 status=3; } } /********************************************************************************************************* ** Function name: recoder_enter_rec_mode ** Descriptions: 进入录音模式 ** input parameters: agc 增益 ** output parameters: 无 ** Returned value: 无 *********************************************************************************************************/ void recoder_enter_rec_mode(u16 agc) { Vs1003_CMD_Write(SPI_AICTRL0,0x0012); //设置采样率,设置为8Khz Vs1003_CMD_Write(SPI_AICTRL1,agc); //设置增益,0,自动增益.1024相当于1倍,512相当于0.5倍,最大值65535=64倍 Vs1003_CMD_Write(SPI_MODE,0x3804); //MIC,录音激活 Vs1003_CMD_Write(SPI_BASS,0x0000); Vs1003_CMD_Write(SPI_CLOCKF,0X9800); delay_ms(200); } /********************************************************************************************************* ** Function name: recoder_play ** Descriptions: 开始录音 ** input parameters: 无 ** output parameters: 无 ** Returned value: 无 *********************************************************************************************************/ u8 recbuf[512]={0}; void recoder_play(void) { u8 res; u8 key; u32 sectorsize=0,CAL=0; u32 sectorCount=1; int i=0; u16 w; u16 idx=0; recoder_enter_rec_mode(0x1000); while(Vs1003_REG_Read(SPI_HDAT1)>>8); res=f_open(&fsrc,'test.wav', FA_CREATE_ALWAYS | FA_WRITE); f_write(&fsrc,(const void*)wav_dat,sizeof(wav_dat),&bw);//写入头数据 ReFresh('Recode'); while(status == 1) { idx=Vs1003_REG_Read(SPI_HDAT1); if((idx>=256)&&(idx<896)) { idx=0; while(idx<512) //一次读取512字节 { w=Vs1003_REG_Read(SPI_HDAT0); recbuf[idx++]=w>>8; recbuf[idx++]=w&0xFF; } res=f_write(&fsrc,recbuf,512,&bw);//写入文件 if(res) { ReFresh('write error'); } sectorsize++; } } Vs1003SoftReset(); for(i=0;i<56;i++) { wav_dat[i]=RIFFHeader0[i]; } for(i=52;i<504;i++) { wav_dat[i]=0; } for(i=504;i<512;i++) { wav_dat[i]=RIFFHeader504[i-504]; } CAL=(sectorsize-1)*1010; wav_dat[48]=(CAL&0xff); wav_dat[49]=((CAL>>8)&0xff); wav_dat[50]=((CAL>>16)&0xff); wav_dat[51]=((CAL>>24)&0xff); CAL=(sectorsize*512)-8; //总长度,RIFF块后(整个wav文件大小-8) wav_dat[4]=(CAL&0xff); wav_dat[5]=((CAL>>8)&0xff); wav_dat[6]=((CAL>>16)&0xff); wav_dat[7]=((CAL>>24)&0xff); CAL = (sectorsize-1)*512; //真实录音数据大小,Data块后 wav_dat[508]=(CAL&0xff); wav_dat[509]=((CAL>>8)&0xff); wav_dat[510]=((CAL>>16)&0xff); wav_dat[511]=((CAL>>24)&0xff); f_lseek(&fsrc,0); //偏移到文件头. f_write(&fsrc,(const void*)wav_dat,sizeof(wav_dat),&bw);//写入头数据 f_close(&fsrc); sectorsize=0; } /********************************************************************************************************* ** Function name: Fatfs_test ** Descriptions: 文件系统写测试 ** input parameters: 无 ** output parameters: 无 ** Returned value: 无 *********************************************************************************************************/ void Fatfs_test(void) { u16 i; for(i=0;i<=512;i++) recbuf[i]=i; res=f_open(&fsrc,'321.txt', FA_OPEN_ALWAYS | FA_WRITE ); if(res) { ReFresh('open error'); f_close(&fsrc); while(1); } for(i=0;i<512;i++) { res=f_write(&fsrc,recbuf,512,&bw);//写入文件 if(res) { ReFresh('test error'); f_close(&fsrc); while(1); } } f_close(&fsrc); ReFresh('test ok'); } /***************************************************************************** ** Main Function main() ******************************************************************************/ int main (void) { u8 i; u16 AD_value,AD_Old_value; SystemInit(); LCD_Init(); //LCD初始化 LCD_SetTextColor(Red);//设置字体为红色 LCD_SetBackColor(Black); //设置背景色为黑色 Vs1003_Init(); //vs1003引脚初始化 Vs1003SoftReset(); //vs1003软件复位 ReFresh(''); //刷新屏幕 USER_ADC_Init(); BUTTON_init(); res=SD_Init(); //初始化SD卡 if(res==0) ReFresh('SD Init OK!!'); f_mount(0,&fs); //挂载文件系统 res=f_opendir(&dirs, '/'); // VsSineTest(); //正弦波测试 ,会听到滴答声 ,说明VS1003 初始化通过 // Fatfs_test(); //文件系统读写测试 while(1) { if(status == 1) { recoder_play(); } else if(status == 2) { ReFresh('Save and Play'); bw = f_open(&fsrc,'test.wav',FA_OPEN_EXISTING | FA_READ); datasize=0; while(status == 2) { if(datasize>=fsrc.fsize) //到达文件尾播放完成 break; if(count++==10) { count=0; AD_value=USER_ADC_Get(); //获取AD转换值 if(abs(AD_value-AD_Old_value)>30) { AD_Old_value = AD_value; AD_value=((AD_value*255)/4096); AD_value<<=8; AD_value+=((AD_Old_value*255)/4096); Vs1003_CMD_Write(SPI_VOL,AD_value); //设音量 高八位为左声道 第八位为右声道,这里相同 } } datasize+=512; //要放到上面 bw = f_read(&fsrc,buffer,512,&br); //读取512字节 for(i=0;i<16;i++) { while(!(LPC_GPIO0->FIOPIN&MP3_DREQ)); Vs1003_DATA_Write(buffer+i*32); } } ……………………