待編輯
CH57x,ch58x的 PWM的能力以及實現
本文所用的PWM為ch57x,58x的timer的pwm功能,而不是那個簡單的專用的pwm外設
選擇合適的音源
音源的關鍵參數:采樣率,量化位寬
- 采樣率:每秒采多少次,單位為Hz,這個跟我們的PWM的頻率相關,不對應會導致我們的實際音頻速度快或慢,這個值的大小會影響聲音的沉悶程度,人的聽覺范圍是20k左右,根據奈奎斯特采樣定理,要進行最小2倍的采樣速度,所以一般我們聽的音樂使用44.1Khz的采樣率
- 量化位寬:每次采樣按照多少個位的ADC去量化(這里還要分均勻量化,和非均勻量化,這里我們需要線性均勻量化的LPCM編碼)
ch57x/58x對應的pwm播放音頻在常用主頻下不同的量化位寬的音源的最大采樣率:
主頻 | 8bit | 12bit(用16bit音源) |
---|---|---|
60M | 234.375K | 14.6484375 K |
48M | 187.5K | 11.71875K |
32M | 125K | 7.8125K |
音頻轉換工具
- ffmpeg(本文使用)
- cooledit\Au
- 其他能轉換為wav文件的工具
音頻文件處理
#把其他的音頻文件轉換成wav文件,LPCM 8bit 無符號,單聲道,14648hz采樣率,注意轉換后的大小
ffmpeg -i windows_phone.mp3 -bitexact -acodec pcm_u8 -ac 1 -ar 14648 windows_phone_8bit_14648hz.wav
#wav文件轉換成hex文件(燒錄方便),這里我們把偏移地址設置為40K的地方,前面放我們的代碼
bin2hex.exe --offset=40960 windows_phone_8bit_14648hz.wav windows_phone_8bit_14648hz.wav.hex
代碼實現
初始化PWM
void ch57x_timer2_pwm_init(uint8_t remap_enable) {
if(remap_enable) {
//timer2 remap gpio at GPIOB
GPIOPinRemap(ENABLE, RB_PIN_TMR2);
GPIOB_ResetBits( GPIO_Pin_11 );
GPIOB_ModeCfg( GPIO_Pin_11, GPIO_ModeOut_PP_20mA );
}else{
GPIOPinRemap(DISABLE, RB_PIN_TMR2);
GPIOA_ResetBits( GPIO_Pin_11 );
GPIOA_ModeCfg( GPIO_Pin_11, GPIO_ModeOut_PP_20mA );
}
//active high
//oversampling = 16,
TMR2_PWMInit( High_Level, PWM_Times_16 );
//disable out here
TMR2_Disable();
//8bit
//60M/16/256 = 14648Hz ,so the wav file should be 14648Hz
//actual output = 60M/256 = 234375hz
TMR2_PWMCycleCfg( 255 );
TMR2_ITCfg(ENABLE,RB_TMR_IE_FIFO_HF);
//clear interrupt flag
TMR2_ClearITFlag(0XFF);
#ifdef CH573
//enable interrupt
PFIC_EnableIRQ( TMR2_IRQn );
#else
NVIC_EnableIRQ( TMR2_IRQn );
#endif
}
分析wav文件
見附件,主要是獲取采樣率,位寬,聲道,和長度信息, 由於不是做通用的wav播放器,這里我們用了長度信息,其他信息只是打印了出來
送入wav波形給到pwm
#ifdef CH573
__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
void TMR2_IRQHandler(void) {
#else
void TMR2_IRQHandler(void) {
#endif
if(TMR2_GetITFlag(TMR0_3_IT_FIFO_HF)) {
TMR2_PWMActDataWidth(((uint32_t)*current_sample_addr));
sample_current ++;
current_sample_addr++;
if(sample_current >= sample_cnt) {
current_sample_addr = (uint8_t *)(WAV_START_ADDR+44);
sample_current = 0;
}
}
//clear all interrput flag
TMR2_ClearITFlag(0XFF);
}
合並音頻與燒錄
合並上面我們處理好的音頻文件
mergehex.exe -m ch58x_pwm_wav_player.hex windows_phone_8bit_14648hz.wav.hex -o ch58x_wav_player_windows_phone_8bit_14648hz.hex
燒錄最終輸出的hex文件:(可以參考文章:https://www.cnblogs.com/iot-fan/p/13498088.html)
ch58x_wav_player_windows_phone_8bit_14648hz.hex
不足
- wav文件體積過大
改進
- 引入音頻編解碼算法,燒錄壓縮后的文件大大降低音源的大小
附件
- 附件工程,以及一些已經處理好的音源文件,拷貝到wch官網sdk的exam文件下編譯:https://gitee.com/iot-fan/iot-fan_at_cnblogs/tree/master/CH581_CH582_CH583/AN/ch58x_pwm_wav_player_v1.1
- 所用到的hex處理工具:https://gitee.com/iot-fan/iot-fan_at_cnblogs/tree/master/Tools/hex_tools
- ffmpeg可以自行到網上找