1.硬件平臺
屏幕:3.5寸TFTLCD屏
音頻解碼器: VS1053
2.示例效果
3.音頻解碼VS1053簡介
VS1053b 是單片 Ogg Vorbis/MP3/AAC/WMA/MIDI 音頻解碼器,及 IMA ADPCM 編碼器和用戶加載的 OggVorbis 編碼器。
支持: MP3/WMA/OGG/WAV/FLAC/MIDI/AAC 等音頻格式的解碼,并支持: OGG/WAV 音頻格式的錄音,支持高低音調(diào)節(jié)設(shè)置, 功能十分強(qiáng)大。
它包含了一個(gè)高性能、有專利的低功耗 DSP 處理器內(nèi)核VS_DSP4、工作數(shù)據(jù)存儲器、供用戶應(yīng)用程序和任何固化解碼器一起運(yùn)行的 16 KiB 指令 RAM 及 0.5KiB 多的數(shù)據(jù) RAM、串行的控制和輸入數(shù)據(jù)接口、最多 8 個(gè)可用的通用 I/O 引腳、一個(gè) UART、并有一個(gè)優(yōu)質(zhì)的可變采樣率立體聲 ADC(“咪”、“線路”、“線路+咪”或“線路*2”) 和立體聲 DAC、和跟隨的一個(gè)耳機(jī)功放及一個(gè)公共電壓緩沖器。
特性:
●能解碼 MPEG 1 和 MPEG2 音頻 層 III( CBR+VBR+ABR); WMA 4.0/4.1/7/8/9 5-384kbps 所有流文件;WAV(PCM+IMA AD-PCM);產(chǎn)生 MIDI/SP-MIDI 文件。
●對話筒輸入或線路輸入的音頻信號進(jìn)行 IMA ADPCM 編碼
●支持 MP3 和 WAV 流
●高低音控制
●單時(shí)鐘操作 12..13MHz
●內(nèi)部 PLL 鎖相環(huán)時(shí)鐘倍頻器
●低功耗
●內(nèi)含高性能片上立體聲數(shù)模轉(zhuǎn)換器, 兩聲道間無相位差
●內(nèi)含能驅(qū)動(dòng) 30 歐負(fù)載的耳機(jī)驅(qū)動(dòng)器
●模擬, 數(shù)字, I/O 單獨(dú)供電
●為用戶代碼和數(shù)據(jù)準(zhǔn)備的 5.5KB 片上 RAM
●串行的控制,數(shù)據(jù)接口
●可被用作微處理器的從機(jī)
●特殊應(yīng)用的 SPI Flash 引導(dǎo)
●供調(diào)試用途的 UART 接口
●新功能可以通過軟件和 4 GPIO 添加
3.1 硬件接口
引腳 | GPIO | 說明 |
---|---|---|
VS_MISO | PA6 | 主機(jī)輸入 |
VS_MOSI | PA7 | 主機(jī)輸出 |
VS_SCK | PA5 | 時(shí)鐘 |
VS_XCS | PF7 | 命令片選(低電平有效) |
VS_XDCS | PF6 | 數(shù)據(jù)片選(低電平有效) |
VS_DREQ | PC13 | 數(shù)據(jù)請求線(高電平表示可以接收數(shù)據(jù)) |
VS_RST | PE6 | 復(fù)位腳(低電平復(fù)位) |
VS1053通訊方式為SPI實(shí)現(xiàn)數(shù)據(jù)傳輸,分為 SDI 和 SCI, SDI 用來傳輸數(shù)據(jù), SCI 用于傳輸命令。
SDI 數(shù)據(jù)傳輸非常簡單,就是標(biāo)準(zhǔn)的 SPI 通信,不過 VS1053 的數(shù)據(jù)傳輸都是通過 DREQ 控制到主機(jī)必須在
判斷 DREQ 有效(高電平有效)后,才可以發(fā)送數(shù)據(jù)。
SCI 命令傳輸接口包含了一個(gè)指令字節(jié)、一個(gè)地址字節(jié)和一個(gè) 16 位的數(shù)據(jù)字。讀寫操作可以讀寫單個(gè)寄存
器,在 SCK 的上升沿讀出數(shù)據(jù)位,所以主機(jī)必須在下降沿刷新數(shù)據(jù)。 SCI 的字節(jié)數(shù)據(jù)總是高位在前低位在后的。
第一個(gè)字節(jié)指令字節(jié),只有 2 個(gè)指令,也就是讀和寫,讀指令為:0X03,寫指令為:0X02。
SCI讀操作:
VS1053b 使用下列時(shí)序?qū)?a href="http://m.1cnz.cn/tags/寄存器/" target="_blank">寄存器進(jìn)行讀取操作,它顯示在圖 6 中。首先, XCS 信號線被拉到低電平來片選此設(shè)備。隨后,讀取操作碼(0x3)加上 8 位寬度的地址后,組成的 16 位字通過 SI 信號線發(fā)送到設(shè)備。在地址被讀取之后, SI 信號線上發(fā)送的任何數(shù)據(jù)都將被芯片忽略。而被確認(rèn)的地址中的十六位寬度數(shù)據(jù)將在 SO 信號線上移動(dòng)輸出。
XCS 信號應(yīng)該在數(shù)據(jù)移動(dòng)送出之后驅(qū)動(dòng)到高電平。
DREQ 在讀取操作期間會(huì)被芯片短暫的拉到低電平,這是非常短的時(shí)間,并不需要用戶特別的留意。
SCI寫操作:
寫入 VS1053b 寄存器的操作要使用下列順序,它顯示在圖 7 中。 XCS 信號線先下拉到低電平表示選中該設(shè)備。將寫操作碼 (0x2) 加上 8 位的字地址通過 SI 信號線發(fā)送到 VS1053b。
在這個(gè)數(shù)據(jù)字移位發(fā)送的最后一個(gè)時(shí)鐘結(jié)束之后, XCS 應(yīng)該上拉到高電平來結(jié)束這個(gè)寫入順序。
VS1053寄存器列表
VS1053 總共有16 個(gè)SCI 寄存器, 通過這些寄存器實(shí)現(xiàn)對 VS1053 的各種控制, VS1053 的所有 SCI 寄存器。
3.2 VS1053驅(qū)動(dòng)
/**************硬件接口*****************
**VS_MISO -- PA6 主機(jī)輸入
**VS_MOSI -- PA7 主機(jī)輸出
**VS_SCK -- PA5 時(shí)鐘
**VS_XCS -- PF7 命令片選(低電平有效)
**VS_XDCS -- PF6 數(shù)據(jù)片選(低電平有效)
**VS_DREQ -- PC13 數(shù)據(jù)請求線(高電平表示可以接收數(shù)據(jù))
**VS_RST -- PE6 復(fù)位腳(低電平復(fù)位)
**
*****************************************/
void VS1053_Init(void)
{
/*1. 開時(shí)鐘*/
RCC->APB2ENR|=1<<2;//PA
RCC->APB2ENR|=1<<4;//PC
RCC->APB2ENR|=1<<6;//PE
RCC->APB2ENR|=1<<7;//PF
GPIOA->CRL&=0x000FFFFF;
GPIOA->CRL|=0x38300000;
GPIOF->CRL&=0x00FFFFFF;
GPIOF->CRL|=0x33000000;
GPIOC->CRH&=0xFF0FFFFF;
GPIOC->CRH|=0x00800000;
GPIOE->CRL&=0xF0FFFFFF;
GPIOE->CRL|=0x03000000;
VS_XCS=1;
VS_XDCS=1;
VS1053_RST();
VS1053_SetVoice(255,255);
/*2.配置時(shí)鐘寄存器*/
VS1053_WriteRegDat(VS1053_CLOCKF,0x9800);
}
/*SPI收發(fā)一個(gè)字節(jié)*/
u8 VS1053_SPI_ReadWriteData(u8 data_tx)
{
u8 data_rx=0;
u8 i=0;
for(i=0;i<8;i++)
{
VS_SCK=0;
if(data_tx&0x80)VS_MOSI=1;
else VS_MOSI=0;
VS_SCK=1;
data_tx<<=1;
data_rx<<=1;
if(VS_MISO)data_rx|=0x01;
}
return data_rx;
}
/********************往寄存器中寫入數(shù)據(jù)******************
**
**形參:u8 addr --地址
** u16 data -- 寫入的數(shù)據(jù)
**********************************************************/
void VS1053_WriteRegDat(u8 addr,u16 data)
{
while(VS_DREQ==0){}//等待數(shù)據(jù)線空閑
VS_XDCS=1;//數(shù)據(jù)片選拉高
VS_XCS=0;//命令片選拉低
VS1053_SPI_ReadWriteData(0x02);//寫指令
VS1053_SPI_ReadWriteData(addr); //寄存器地址
VS1053_SPI_ReadWriteData(data>>8);
VS1053_SPI_ReadWriteData(data>>0);//寫入數(shù)據(jù)
VS_XCS=1;
}
/*******************從寄存器中讀取數(shù)據(jù)*******************/
u16 VS1053_ReadRegDat(u8 addr)
{
u16 data=0;
while(VS_DREQ==0){}//等待數(shù)據(jù)線空閑
VS_XDCS=1;//數(shù)據(jù)片選拉高
VS_XCS=0;//命令片選拉低
VS1053_SPI_ReadWriteData(0x03);//讀指令
VS1053_SPI_ReadWriteData(addr); //寄存器地址
data=VS1053_SPI_ReadWriteData(0xff)<<8;
data|=VS1053_SPI_ReadWriteData(0xff);
VS_XCS=1;
return data;
}
/****************音量調(diào)節(jié)*****************
**
**形參:u8 vol_l -- 左聲道 0~254
** u8 vol_r -- 右聲道 0~254
**每個(gè)增量表示0.5db的衰減,值越大,音量越小
**注意:如果設(shè)置 VOL 的值為 0xFFFF,將使芯片進(jìn)入掉電模式。
**右聲道是高 8 位 左聲道是低 8 位
*******************************************/
void VS1053_SetVoice(u8 vol_l,u8 vol_r)
{
u16 temp=vol_r<<8|vol_l;
VS1053_WriteRegDat(VS1053_VOL,temp);
}
/***************VS1053硬件復(fù)位**************/
void VS1053_RST(void)
{
//硬件復(fù)位
VS_RST=0;
Delay_Ms(20);
VS_XDCS=1;//取消數(shù)據(jù)傳輸
VS_XCS=1;//取消命令傳輸
VS_RST=1;//完成復(fù)位
//軟件復(fù)位
while(VS_DREQ==0){}//等待數(shù)據(jù)線空閑
VS1053_WriteRegDat(VS1053_MODE,0x0804);//設(shè)置為新模式,進(jìn)行軟件復(fù)位
Delay_Ms(2);
while(VS_DREQ==0){}//等待數(shù)據(jù)線空閑,復(fù)位完成
}
/****獲取解碼時(shí)間******/
u16 VS1053_Get_Time(void)
{
u16 time=0;
time=VS1053_ReadRegDat(VS1053_DECODE_TIME);
return time;
}
/****清除解碼時(shí)間******/
void VS1053_Clear_Time(void)
{
VS1053_WriteRegDat(VS1053_DECODE_TIME,0);
}
3.3 播放音樂,歌詞同步,音樂切換
static unsigned char music_lrc[4096];//存放從文件中讀取出來的歌詞
static unsigned char music_lrc_str[100][50];//存放篩選過后的歌詞
static u16 music_time[200];//保存每句歌詞時(shí)間
u8 buff_music[4096];
/**************播放音樂****************************/
u8 VS1053_PlayOneMusic(const char *music_file,u8 display_lrc)
{
u16 i=0,time1,time2;
u32 k=0;
u16 y=32;
u8 vol_l=50,vol_r=50;
FIL fp;
FRESULT res;
UINT br;
u8 key=0;
res=f_open(&fp,music_file,FA_READ);//只讀
if(res!=FR_OK)
{
//printf("%s文件打開失敗err:%d\r\n",music_file,res);
return 1;
}
//printf("VS1053復(fù)位成功\r\n");
LCD_ShowStr2(0,16,(u8 *)music_file,WHITE);//顯示歌名
LCD_Refresh();//更新顯示
VS1053_Clear_Time();//清除解碼時(shí)間
/*3.設(shè)置音量*/
VS1053_SetVoice(50,50);
while(!f_eof(&fp))//判斷是否到文件尾
{
key=Key_Scan();
if(key==1)
{
break;//切換下一首
}
else if(key==2)//聲音加
{
if(vol_l<250)
{
vol_l+=50;
vol_r+=50;
}
VS1053_SetVoice(vol_l,vol_r);
}
else if(key==3)//聲音減
{
if(vol_l>0)
{
vol_l-=50;
vol_r-=50;
}
VS1053_SetVoice(vol_l,vol_r);
}
if(f_read(&fp,buff_music,sizeof(buff_music),&br)!=FR_OK)//讀取音頻數(shù)據(jù)
{
//printf("讀取文件失敗");
f_close(&fp);
return 2;
}
// printf("讀取數(shù)據(jù)成功\r\n");
for(i=0;i
=music_time[k])//通過時(shí)間判斷顯示對應(yīng)歌詞
{
if(y>=(LCD_HIGHT-48))//換頁顯示歌詞
{
y=32;
LCD_ReflashBack();//重畫背景
LCD_ShowStr2(0,16,(u8 *)music_file,WHITE);//顯示歌名
}
LCD_ShowStr2(y,16,music_lrc_str[k],WHITE);//顯示當(dāng)前行
if(k>=1 && y>=48)
{
LCD_ShowStr2(y-16,16,music_lrc_str[k-1],GRAY);//將上一行清為底色
}
LCD_Refresh();//更新顯示
y+=16;
k++;
}
}
}
}
return 0;
}
;i++)>
3.4 讀取音樂文件,查找歌詞,播放音樂
/***********音樂播放***************/
u8 Vs1053_play_Music(const char *music_file)
{
u32 i=0;
u8 stat=0;
DIR dp;
char *p=NULL;
FILINFO fno;
FRESULT res;
char buff1[50];
char buff2[50];
res=f_opendir(&dp,music_file);
if(res!=FR_OK)
{
printf("目錄打開失敗err:%d\r\n",res);
return 1;
}
printf("目錄打卡成功\r\n");
while(1)
{
res=f_readdir(&dp,&fno);
if(res!=FR_OK || fno.fname[0]==0)
{
break;
}
// printf("%s\r\n",fno.fname);
p=strstr(fno.fname,".mp3");//查找文件中的音頻文件
if(p)
{
i=0;
//G.E.M. 鄧紫棋 - 我的秘密
while(1)
{
buff1[i]=fno.fname[i];
if((fno.fname[i]=='.') && (fno.fname[i+1]=='m') && (fno.fname[i+2]=='p') && (fno.fname[i+3]=='3'))break;
i++;
}
buff1[i]='\0';
//顯示歌名
LCD_ReflashBack();//重畫背景
LCD_Refresh();//更新顯示
//printf("歌名:%s\r\n",buff1);
snprintf((char *)buff2,sizeof(buff2),"%s/%s.lrc",music_file,buff1);
//printf("buff2:%s\r\n",buff2);
stat=Vs1053_GetLrc_Music(buff2);//歌詞解析
//if(stat==0)printf("獲取歌詞成功\r\n");
snprintf((char *)buff2,sizeof(buff2),"%s/%s.mp3",music_file,buff1);
stat=VS1053_PlayOneMusic(buff2,!stat);//播放音樂
if(stat==0)
{
printf("音樂播放完成\r\n");
}
else
{
printf("stat=%d\r\n",stat);
}
}
}
f_closedir(&dp);
return 0;
}
3.5 初始化硬件,掛載SD卡設(shè)備,播放音樂
int main()
{
FRESULT ret;
FATFS fs;
Beep_Init();
Led_Init();
Key_Init();
Usartx_Init(USART1,115200,72);
TIMx_Init(TIM2,72,20*1000);
W25Q64_Init();//W25Q64初始化
IIC_Init();//IIC初始化
NT35310_Init();//LCD初始化
SRAM_Init();
AA:
/*掛載磁盤*/
ret=f_mount(&fs,"",1);
if(ret==FR_OK)
{
printf("磁盤掛載成功\n");
}
else
{
printf("請檢查SD卡是否插入!!\r\n");
Delay_Ms(1000);
goto AA;
}
VS1053_Init();
while(1)
{
Vs1053_play_Music("0:/music");
}
}
審核編輯:湯梓紅
-
播放器
+關(guān)注
關(guān)注
5文章
397瀏覽量
37409 -
vs1053
+關(guān)注
關(guān)注
0文章
12瀏覽量
12910 -
STM32F103ZE
+關(guān)注
關(guān)注
2文章
14瀏覽量
10886
發(fā)布評論請先 登錄
相關(guān)推薦
評論