待编辑
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可以自行到网上找