CH579/573/582, 使用PWM播放WAV語音和音樂


待編輯

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文件體積過大

改進

  • 引入音頻編解碼算法,燒錄壓縮后的文件大大降低音源的大小

附件


免責聲明!

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



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