1. 程式人生 > 其它 >host速度 mtk usb_阿波羅 STM32F767 開發板資料連載第六十二章 USB 音效卡實驗

host速度 mtk usb_阿波羅 STM32F767 開發板資料連載第六十二章 USB 音效卡實驗

技術標籤:host速度 mtk usb

1)實驗平臺:alientek 阿波羅 STM32F767 開發板2)摘自《STM32F7 開發指南(HAL 庫版)》關注官方微訊號公眾號,獲取更多資料:正點原子

bb86c5e9666d4737d8b5c792ee5cfeca.png

第六十二章 USB 音效卡(Slave)實驗

上一章我們向大家介紹瞭如何利用 STM32F767 的 USB 介面來做一個 USB 讀卡器,本章我

們將利用 STM32F767 的 USB 來做一個音效卡。本章分為如下幾個部分:

62.1 USB 音效卡簡介

62.2 硬體設計

62.3 軟體設計

62.4 下載驗證

62.1 USB 音效卡簡介

ALIENTEK 阿波羅 STM32F767 開發闆闆載了一顆高效能 CODEC 晶片:WM8978,我們

可以利用 STM32F767 的 SAI 介面,控制 WM8978 播放音樂,同樣,如果結合 STM32F767 的

USB 功能,就可以實現一個 USB 音效卡。

同上一章一樣,我們直接移植官方的 USB AUDIO 例程,官方例程路徑:8,STM32 參考

資料STM32 USB 學習資料STM32_USB-Host-Device_Lib_V2.2.0ProjectUSB_De

vice_ExamplesAUDIO,該例程採用 USB 同步傳輸來傳輸音訊資料流並且支援某些控制命令

(比如靜音控制),例程僅支援 USB FS 模式(不支援 HS),同時例程不需要特殊的驅動支援,

大多數作業系統直接就可以識別。

62.2 硬體設計

本節實驗功能簡介:開機的時候先顯示一些提示資訊,之後開始 USB 配置,在配置成功

之後就可以在電腦上發現多出一個 USB 音效卡。我們用 DS1 來指示 USB 是否連線成功,並在

液晶上顯示 USB 連線狀況,如果成功連線,DS1 會亮,此時,我們可以將耳機插入開發板的

PHONE 埠,聽到來自電腦的音訊訊號,同時通過兩個按鍵可以調節音量:按 KEY0 可以增

大音量,KEY2 可以減少音量。同樣我們還是用 DS0 來指示程式正在執行。

所要用到的硬體資源如下:

1) 指示燈 DS0 、DS1

2) KEY0 和 KEY2 兩個按鍵

3) 串列埠

4) LCD 模組

5) USB SLAVE 介面

6) WM8978

這幾個部分,在之前的例項中都已經介紹過了,我們在此就不多說了。這裡再次提醒大家,

P10 的連線,要通過跳線帽連線 PA11 和 D-以及 PA12 和 D+。

62.3 軟體設計

本章,我們在第五十二章 音樂播放器實驗(實驗 47)的基礎上修改,先開啟實驗 47 的工

程,在 HARDWARE 資料夾所在資料夾下新建一個 USB 的資料夾,同上一章一樣,對照官方

AUDIO 例子,將相關檔案拷貝到 USB 資料夾下。

然後,我們在工程裡面去掉一些不必要的程式碼,並新增 USB 相關程式碼,最終得到如圖 62.3.1

所示的工程:

d2dfb497eff773093430bc320ce876b0.png

圖 59.3.1 USB 音效卡工程截圖

可以看到,USB 部分程式碼,同上一章的在結構上是一模一樣的,只是.c 檔案稍微有些變化。

同樣,我們移植需要修改的程式碼,就是 USB_APP 裡面的這四個.c 檔案了。

其中 usb_bsp.c 和 usbd_usr.c 的程式碼,和上一章基本一樣,可以用上一章的程式碼直接替換即

可正常使用。

usb_desc.c 程式碼,同上一章不一樣,上一章描述符是大容量儲存裝置,本章變成了 USB 聲

卡了,所以直接用 ST 官方的就行。

最後 stm324xg_usb_audio_codec.c,這裡面的程式碼,是重點要修改的,該檔案是配合 USB

音效卡的 WM8994 底層驅動相關程式碼,官方 STM32F7xx 的板子,用的是 WM8994,而我們用的

是 WM8978,需要修改程式碼,修改後程式碼如下:

u8 volume=0;//當前音量vu8 audiostatus=0;//bit0:0,暫停播放;1,繼續播放vu8 saiplaybuf=0;//即將播放的音訊幀緩衝編號vu8 saisavebuf=0;//當前儲存到的音訊緩衝編號#define AUDIO_BUF_NUM100//由於採用的是 USB 同步傳輸資料播放//而 STM32 SAI 的速度和 USB 傳送過來資料的速度存在差異,比如在 48Khz 下,實//際 SAI 是低於 48Khz(47.991Khz)的,所以電腦送過來的資料流,會比 STM32 播放//速度快,緩衝區寫位置追上播放位置(saisavebuf==saiplaybuf)時,就會出現//混疊.設定儘量大的 AUDIO_BUF_NUM 值,可以儘量減少混疊次數. u8 *saibuf[AUDIO_BUF_NUM]; // 音訊緩衝幀 , 佔 用 內 存 數=AUDIO_BUF_NUM*AUDIO_OUT_PACKET 位元組 //音訊資料 SAI DMA 傳輸回撥函式void audio_sai_dma_callback(void) { if((saiplaybuf==saisavebuf)&&audiostatus==0){ SAI_Play_Stop();}else{saiplaybuf++;if(saiplaybuf>(AUDIO_BUF_NUM-1))saiplaybuf=0;if(DMA2_Stream1->CR&(1<<19)){DMA2_Stream1->M0AR=(u32)saibuf[saiplaybuf];//指向下一個 buf }else { DMA2_Stream1->M1AR=(u32)saibuf[saiplaybuf];//指向下一個 buf } }} //配置音訊介面//OutputDevice:輸出裝置選擇,未用到.//Volume:音量大小,0~100//AudioFreq:音訊取樣率uint32_t EVAL_AUDIO_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq){ u16 t=0;for(t=0;t(AUDIO_BUF_NUM-1))t=0; if(t==curplay) //寫快取碰上了當前正在播放的幀,跳到下一幀{t++;if(t>(AUDIO_BUF_NUM-1))t=0; printf("bad position:%d",t);}saisavebuf=t;for(i=0;i

這裡特別說明一下,USB AUDIO 我們使用的是 USB 同步資料傳輸,音訊取樣率固定為:

48Khz(通過 USBD_AUDIO_FREQ 設定,在 usbd_conf.h 裡面),這樣,USB 傳輸過來的資料

都是 48Khz 的音訊資料流,STM32F767 必須以同樣的頻率傳輸資料給 SAI,以同步播放音樂。

但是,STM32F767 我們採用的是外部 25M 時鐘倍頻後分頻作為 SAI 時鐘的,在使能主時

鍾(MCK)輸出的時候,只能以 47.991Khz 頻率播放,稍微有點誤差,這樣,導致 USB 送過

來的資料,會比傳輸給 SAI 的資料快一點點,如果不做處理,就很容易產生資料混疊,產生噪

音。

因此,我們這裡提供了一個簡單的解決辦法:建立一個類似 FIFO 結構的緩衝陣列,USB

傳輸過來的資料全部存放在這些數組裡面,同時通過 SAI DMA 雙緩衝機制,播放這些數組裡

面的音訊資料,當混疊發生時(USB 傳過來的資料,趕上 SAI 播放的資料了),直接越過當前

正在播放的陣列,繼續儲存。這樣,雖然會導致一些資料丟失(混疊時),但是避免了混疊,保

證了良好的播放效果(聽不到噪音),同時,陣列個數越多,效果就越好(越不容易混疊)。

以上程式碼 AUDIO_BUF_NUM 就是我們定義的 FIFO 結構陣列的大小,越大,效果越好,

這裡我們定義成 100,每個陣列的大小由音訊取樣率和位數決定,計算公式為:

(USBD_AUDIO_FREQ * 2 * 2) /1000

單位為位元組,其中 USBD_AUDIO_FREQ 即音訊取樣率:48Khz,這樣,每個陣列大小就

是 192 位元組。100 個數組,我們總共用了 19200 位元組。

audio_sai_dma_callback 函式是 SAI 播放音訊的回撥函式,完成 SAI 資料流的傳送(切換

DMA 源地址),其他函式則基本都是在 usbd_audio_out_if.c 裡面被呼叫,這裡就不再詳細介紹

了。

最後在 main.c 裡面,我們修改 main 函式如下:

USB_OTG_CORE_HANDLE USB_OTG_dev;extern vu8 bDeviceState; //USB 連線 情況extern u8 volume; //音量(可通過按鍵設定)int main(void){u8 key;u8 t=0;u8 Divece_STA=0XFF;  Cache_Enable(); //開啟 L1-Cache HAL_Init(); //初始化 HAL 庫 Stm32_Clock_Init(432,25,2,9); //設定時鐘,216Mhz  delay_init(216); //延時初始化uart_init(115200); //串列埠初始化 LED_Init(); //初始化 LED KEY_Init(); //初始化按鍵 SDRAM_Init(); //初始化 SDRAM LCD_Init(); //初始化 LCD W25QXX_Init(); //初始化 W25Q256 PCF8574_Init(); //初始化 PCF8574  WM8978_Init(); //初始化 WM8978WM8978_ADDA_Cfg(1,0); //開啟 DACWM8978_Input_Cfg(0,0,0); //關閉輸入通道WM8978_Output_Cfg(1,0); //開啟 DAC 輸出my_mem_init(SRAMIN); //初始化內部記憶體池my_mem_init(SRAMEX); //初始化外部記憶體池my_mem_init(SRAMDTCM); //初始化 DTCM 記憶體池  POINT_COLOR=RED;//設定字型為紅色 LCD_ShowString(30,50,200,16,16,"Apollo STM32F4/F7");LCD_ShowString(30,70,200,16,16,"USB Sound Card TEST");LCD_ShowString(30,90,200,16,16,"[email protected]");LCD_ShowString(30,110,200,16,16,"2016/8/10");LCD_ShowString(30,130,200,16,16,"KEY2:Vol- KEY0:vol+");POINT_COLOR=BLUE;//設定字型為藍色LCD_ShowString(30,160,200,16,16,"VOLUME:"); //音量顯示 LCD_ShowxNum(30+56,160,DEFAULT_VOLUME,3,16,0X80);//顯示音量LCD_ShowString(30,180,200,16,16,"USB Connecting...");//提示正在建立連線 USBD_Init(&USB_OTG_dev,USB_OTG_FS_CORE_ID,&USR_desc,&AUDIO_cb,&USR_cb); while(1){ key=KEY_Scan(1);//支援連按if(key){  if(key==KEY0_PRES) //KEY0 按下,音量增加{volume++;if(volume>100)volume=100; }else if(key==KEY2_PRES)//KEY2 按下,音量減少{ if(volume)volume--;else volume=0;} EVAL_AUDIO_VolumeCtl(volume);LCD_ShowxNum(30+56,160,volume,3,16,0X80);//顯示音量delay_ms(20);} if(Divece_STA!=bDeviceState)//狀態改變了{if(bDeviceState==1){LED1(0);LCD_ShowString(30,180,200,16,16,"USB Connected ");//提示 USB 連線已經建立}else {LED1(1);LCD_ShowString(30,180,200,16,16,"USB DisConnected ");//提示 USB 連線失敗}Divece_STA=bDeviceState;}delay_ms(20);t++;if(t>10){t=0;LED0_Toggle;} } }

此部分程式碼比較簡單,同上一章一樣定義了 USB_OTG_dev 結構體,然後通過 USBD_Init

初始化 USB,不過本章實現的是 USB 音效卡功能。本章我們保留了原例程(實驗 47)的 USMART

部分,同樣可以通過串列埠 1 設定 WM8978 相關引數。

其他部分我們就不詳細介紹了,軟體設計部分就為大家介紹到這裡。

62.4 下載驗證

在程式碼編譯成功之後,我們通過下載程式碼到阿波羅 STM32 開發板上,在 USB 配置成功後

(注意:USB 資料線,要插在 USB_SLAVE 埠!不是 USB_232 埠!另外,USB_HOST 接

口不要插任何外設!),LCD 顯示效果如圖 62.4.1 所示:

eb52caf3f1409d97a6ef0f1ed1f49136.png

圖 62.4.1 USB 連線成功

此時,電腦提示發現新硬體,並自動完成驅動安裝,如圖 62.4.2 所示:

372e9a4b931af9bf82471c4368593c27.png

圖 62.4.2 電腦找到 ALIENTEK USB 音效卡

等 USB 配置成功後,DS1 常亮,DS0 閃爍,並且在裝置管理器聲音、視訊和遊戲控制器

裡面看到多了 ALIENTEK STM32F4/F7 USB AUDIO 裝置,如圖 62.4.3 所示:

c04a7f3a556ad1bb5611860688dca643.png

圖 62.4.3 裝置管理器找到 ALIENTEK USB 音效卡

然後,設定 ALIENTEK STM32F4/F7 USB AUDIO 為電腦的預設播放裝置,則電腦的所有

聲音都被切換到開發板輸出,將耳機插入阿波羅 STM32 開發板的 PHONE 埠,即可聽到來自

電腦的聲音。通過按鍵 KEY0/KEY2 可以增大/減少音量,預設音量設定的是 65,大家可以自己

調節(範圍:0~100)。