記錄下,折騰了兩天終於可以播放聲音了,Stm32f103 使用DAC播放wav音頻文件


 

 

 00-03    52 49 46 46:RIFF的標志

04-07    24 90 01 00 :文件的長度

08-0B    57 41 56 45  :WAVE的標志

0C-0F   66 6D 74 20  :fmt的標志

10-13   10 00 00 00   :編碼的格式類別,10H代表PCM形式。

14-15    01  00  :字塊總數

16-17   01  00   : 通道數  1為單聲道,2為雙聲道

18-1B  80 3E 00 00 :采樣率:每秒采集二進制的位數。

1C-1F  00 7D 00 00 :每秒播放的字節數 = 通道數 x 每秒采集二進制的位數 x 采集數據的位數 / 8.  32000

20-21  02 00 :每個樣點的字節數

22-23  01 00 :每個樣點的數據位數

24-27 64 61 74 61 :data的標志

28-2b:00 90 01 00  文件長度

wav文件長度 3200KB

wav 的頻率為16000

一般WAV數據開始的第44字節開始就是wav數據了,把wav數據取出后直接送到DAC播放。

這里的WAV的dac數據是16bit的需要進行轉換成12bit

voice[i] = voice[i]+0x8000;//16bit dac 數據為補碼形式的,需要進行處理+0x8000
voice[i] = voice[i] >>num; //num 一般為4 右移4位剩下12bit dac數據

設置time定時器的頻率16K的采集率

arrValue = (uint16_t)(72000000/(16000-1));

 

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //時鍾使能
//定時器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = arrValue ; //設置在下一個更新事件裝入活動的自動重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =0; //設置用來作為TIMx時鍾頻率除數的預分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鍾分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據指定的參數初始化TIMx的時間基數單位
TIM_Cmd(TIM3, ENABLE); //使能TIMx

 

DAC 進行初始化:

GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitType;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能PORTA通道時鍾
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能DAC通道時鍾

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模擬輸入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4) ;//PA.4 輸出高

DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用觸發功能 TEN1=0
DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形發生
DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值設置
DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1輸出緩存關閉 BOFF1=1
DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化DAC通道1

DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1

DAC_SetChannel1Data(DAC_Align_12b_R, 0); //DAC_Align_12b_R 12位右對齊數據格式設置DAC值

TIM3->DIER|=1<<8;//允許更新dma請求
TIM3->DIER|=1<<6;//允許觸發中斷
TIM3->DIER|=1<<0;//允許更新中斷

打開DAC DMA功能

DMA_Cmd(DMA1_Channel3, DISABLE ); //關閉USART1 TX DMA1 所指示的通道
DMA_SetCurrDataCounter(DMA1_Channel3,DMA1_MEM_LEN);//DMA通道的DMA緩存的大小
DMA_Cmd(DMA1_Channel3, ENABLE); //使能USART1 TX DMA1 所指示的通道

這樣就可以把WAV的dac數據通過DMA發送出去了

當一包的DMA數據發送完成后需要更新一包數據進行發送,通過定時器中斷設置標志位后,重新配置數據,

下次改用DMA的中斷試試看。

DMA_Cmd(DMA1_Channel3, DISABLE );

DAC_DMA_Config(DMA1_Channel3,(u32)&DAC->DHR12R1,(u32)DAC_SIN_BUF,DAC_SIN_SIZE); 

DMA_SetCurrDataCounter(DMA1_Channel3,DMA1_MEM_LEN);//DMA通道的DMA緩存的大小
DMA_Cmd(DMA1_Channel3, ENABLE); //使能USART1 TX DMA1 所指示的通道

 

直到把數據發送完,簡單的播放wav數據就完成了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM