文章目录
- GD - GD32350R_EVAL - PWM实验和验证2 - EmbeddedBuilder - 无源蜂鸣器
- 概述
- 笔记
- 先前失败的实验电路图
- 本次成功的图 - 无源蜂鸣器电路模块
- 接入实验模块
- 实验软件工程
- 主循环实现
- PWM频率改变蜂鸣器声音大小
- 实验结果和官方给的蜂鸣器频率响应曲线基本一样
- 看看实际波形
- END
GD - GD32350R_EVAL - PWM实验和验证2 - EmbeddedBuilder - 无源蜂鸣器
概述
前面做了一个实验(GD - GD32350R_EVAL - PWM实验和验证1), 确认了如何生成指定频率的PWM波。
今天做了一个实验,用PWM驱动无源蜂鸣器发出声音。
笔记
有源蜂鸣器没找到工业级别的。
无源蜂鸣器有压电式和电磁式。
为了省电,拟采用压电式无源蜂鸣器。
根据自己用的无源蜂鸣器型号,确定发声最高时对应的PWM频率。
现在采用的压电蜂鸣器频率响应曲线对应的最高声音频率为4KHZ.
先前失败的实验电路图
为了省电,想着用PMOS管来控制蜂鸣器电路通断。做了板子实验完,发现不行(蜂鸣器基本不发声,不是频率不对,而是真的就基本没声音),用示波器看波形,不是方波(而是上升沿为90度,中间会有一个电压保持的平台,然后是一段线性下降的下降沿),且压差只有2.2V。
应该是PMOS没进入饱和状态导致的。
查了资料,为了使MOS进入饱和状态,UGS压差要10V以上。
UGS > UGSth 只是能将MOS导通,对于信号传递来说没问题。
但是对于电压波形来说,就不合适了。
怪不得查的资料中,没有人用MOS管来控制蜂鸣。
没实验的情况:
- R9我用的是100R, 按照这次实验来说,我应该用0R. 不用限流
- 官方推荐在蜂鸣器2边并联1K的电阻,在失败图上我没并联。
实验的没那么细致,需要时间成本。等以后有时间,再继续实验,看看失败图是否可以改进为有效控制蜂鸣器。
本次成功的图 - 无源蜂鸣器电路模块
为了微调,在电路中串入了电阻(R_ADJ_1/R_ADJ_2), 实验中没有调整,R1/R6都是0R. R2/R3/R4/R7/R8/R9都是NC
用跳线连接了R_ADJ1/R_ADJ_1A, R_ADJ2/R_ADJ2A, 联通了电路。
剩下的元件都是按照电路图来。
接口端子为VCC_3V3/GND/GPIO_BEEP.
接入实验模块
实验平台为 GD32350R_EVAL
找合适的端子接入VCC_3V3/GND.
PA8接入GPIO_BEEP
实验软件工程
直接在 EmbeddedBuilder_v1.4.1.23782\examples\GD32F3x0\examples\CMP\CMP_pwm_signal_control 官方工程上改的。
拿官方工程跑一遍(图形化产生代码,编译,run),蜂鸣器可以发声。这时PWM是100HZ, 蜂鸣器声音不是很大。
主循环实现
将主循环代码,改一下,让每次run都能听到连续的滴滴声,听清楚了,就不发声了。
int main(void)
{/* user code [local 0] begin */int beep_cnt = 0;/* user code [local 0] end */msd_system_init();msd_clock_init();/* user code [local 1] begin *//* user code [local 1] end */msd_gpio_init();msd_cmp0_init();msd_timer0_init();/* user code [local 2] begin */// hal_cmp_start(&cmp0_info);// hal_timer_output_compare_start(&timer0_info, TIMER_CH_0);/* user code [local 2] end */while(1){/* user code [local 3] begin */if (beep_cnt < 200){beep_cnt++;hal_timer_output_compare_start(&timer0_info, TIMER_CH_0);hal_sys_basetick_delay_ms(30);hal_timer_output_compare_stop(&timer0_info, TIMER_CH_0);hal_sys_basetick_delay_ms(70);}/* user code [local 3] end */}
}
看了gd32f3x0_hal_timer.h, 没看到有方便改变占空比的API.
就用 hal_timer_output_compare_start 开始PWM, 用 hal_timer_output_compare_stop 停止PWM
先这么着.
PWM频率改变蜂鸣器声音大小
做实验时,需要改的初始化代码为PWM载入计数和方波计数。这时,直接改就行,不再需要图形化配置。
反正频率范围也不宽,就手工改,改一次,跑一下,听一下声音,然后和官方的蜂鸣器频率响应图对一下。
void msd_timer0_init(void)
{/* user code [timer0_init local 0] begin *//* user code [timer0_init local 0] end */hal_gpio_init_struct gpio_init_parameter;hal_timer_init_struct timer0_init_parameter;hal_timer_output_compare_struct timer0_output_compare_parameter;hal_timer_clear_source_struct timer0_clear_source_parameter;hal_timer_break_struct timer0_break_parameter;hal_rcu_periph_clk_enable(RCU_TIMER0);hal_gpio_struct_init(&gpio_init_parameter);gpio_init_parameter.mode = GPIO_MODE_AF_PP;gpio_init_parameter.pull = GPIO_PULL_NONE;gpio_init_parameter.ospeed = GPIO_OSPEED_50MHZ;gpio_init_parameter.af = GPIO_AF_2;hal_gpio_init(GPIOA, GPIO_PIN_8, &gpio_init_parameter);hal_timer_struct_init(HAL_TIMER_INIT_STRUCT, &timer0_init_parameter);hal_timer_struct_init(HAL_TIMER_DEV_STRUCT, &timer0_info);hal_timer_struct_init(HAL_TIMER_OUTPUT_COMPARE_STRUCT, &timer0_output_compare_parameter);hal_timer_struct_init(HAL_TIMER_CLEAR_SOURCE_STRUCT, &timer0_clear_source_parameter);hal_timer_struct_init(HAL_TIMER_BREAK_STRUCT, &timer0_break_parameter);timer0_init_parameter.prescaler = 107;timer0_init_parameter.alignedmode = TIMER_COUNTER_EDGE;timer0_init_parameter.counter_direction = TIMER_COUNTER_UP;// PWM = 100HZ, 1 / PWM = 0.01S = 0.01 * 1000000us = 10000us,// auto_load = 10000 - 1// pulse =auto_load / 2 - 1 = 5000 - 1// PWM = 200HZ, 1 / PWM = 0.005S = 0.005 * 1000000us = 5000us,// auto_load = 5000 - 1 = 4999// pulse =auto_load / 2 - 1 = 5000/2 - 1 = 2500 - 1 = 2499// PWM = 300HZ, 1 / PWM = 0.003S = 0.003 * 1000000us = 3000us,// auto_load = 3000 - 1 = 2999// pulse =auto_load / 2 - 1 = 3000/2 - 1 = 1500 - 1 = 1499// PWM = 400HZ, 1 / PWM = 0.0025S = 0.0025 * 1000000us = 2500us,// auto_load = 2500 - 1 = 2499// pulse =auto_load / 2 - 1 = 2500/2 - 1 = 1250 - 1 = 1249// PWM = 500HZ, 1 / PWM = 0.002S = 0.002 * 1000000us = 2000us,// auto_load = 2000 - 1 = 1999// pulse =auto_load / 2 - 1 = 2000/2 - 1 = 1000 - 1 = 999// PWM = 600HZ, 1 / PWM = 0.0016S = 0.0016 * 1000000us = 1600us,// auto_load = 1600 - 1 = 1599// pulse =auto_load / 2 - 1 = 1600/2 - 1 = 800 - 1 = 799// PWM = 700HZ, 1 / PWM = 0.0014S = 0.0014 * 1000000us = 1400us,// auto_load = 1400 - 1 = 1399// pulse =auto_load / 2 - 1 = 1400/2 - 1 = 700 - 1 = 699// PWM = 800HZ, 1 / PWM = 0.00125S = 0.00125 * 1000000us = 1250us,// auto_load = 1250 - 1 = 1249// pulse =auto_load / 2 - 1 = 1250/2 - 1 = 625 - 1 = 624// PWM = 900HZ, 1 / PWM = 0.001111S = 0.001111 * 1000000us = 1111us,// auto_load = 1111 - 1 = 1110// pulse =auto_load / 2 - 1 = 1111/2 - 1 = 556 - 1 = 555// PWM = 1000HZ, 1 / PWM = 0.001000S = 0.001000 * 1000000us = 1000us,// auto_load = 1000 - 1 = 999// pulse =auto_load / 2 - 1 = 1000/2 - 1 = 500 - 1 = 499// 8.3333333333333333333333333333333e-4// PWM = 1200HZ, 1 / PWM = 0.000833S = 0.000833 * 1000000us = 833us,// auto_load = 833 - 1 = 832// pulse =auto_load / 2 - 1 = 833/2 - 1 = 417 - 1 = 416// 7.1428571428571428571428571428571e-4// PWM = 1400HZ, 1 / PWM = 0.000714S = 0.000714 * 1000000us = 714us,// auto_load = 714 - 1 = 713// pulse =auto_load / 2 - 1 = 714/2 - 1 = 357 - 1 = 356// 0.000625// PWM = 1600HZ, 1 / PWM = 0.000625S = 0.000625 * 1000000us = 625us,// auto_load = 625 - 1 = 624// pulse =auto_load / 2 - 1 = 625/2 - 1 = 313 - 1 = 312// 0.000555// PWM = 1800HZ, 1 / PWM = 0.000555S = 0.000555 * 1000000us = 555us,// auto_load = 555 - 1 = 554// pulse =auto_load / 2 - 1 = 555/2 - 1 = 278 - 1 = 277// 0.000500// PWM = 2000HZ, 1 / PWM = 0.000500S = 0.000500 * 1000000us = 500us,// auto_load = 500 - 1 = 499// pulse =auto_load / 2 - 1 = 500/2 - 1 = 250 - 1 = 249// 0.000416// PWM = 2400HZ, 1 / PWM = 0.000416S = 0.000416 * 1000000us = 416us,// auto_load = 416 - 1 = 415// pulse =auto_load / 2 - 1 = 416/2 - 1 = 208 - 1 = 207// 0.000357// PWM = 2800HZ, 1 / PWM = 0.000357S = 0.000357 * 1000000us = 357us,// auto_load = 357 - 1 = 356// pulse =auto_load / 2 - 1 = 357/2 - 1 = 179 - 1 = 178// 0.000313// PWM = 3200HZ, 1 / PWM = 0.000313S = 0.000313 * 1000000us = 313us,// auto_load = 313 - 1 = 312// pulse =auto_load / 2 - 1 = 313/2 - 1 = 157 - 1 = 156// 0.000277// PWM = 3600HZ, 1 / PWM = 0.000277S = 0.000277 * 1000000us = 277us,// auto_load = 277 - 1 = 276// pulse =auto_load / 2 - 1 = 277/2 - 1 = 139 - 1 = 138// 0.000250// PWM = 4000HZ, 1 / PWM = 0.000250S = 0.000250 * 1000000us = 250us,// auto_load = 250 - 1 = 249// pulse =auto_load / 2 - 1 = 250/2 - 1 = 125 - 1 = 124timer0_init_parameter.period = 249;timer0_init_parameter.clock_division = TIMER_CKDIV_DIV1;timer0_init_parameter.repetition_counter = 0;timer0_init_parameter.autoreload_shadow = TIMER_CARL_SHADOW_DISABLE;timer0_init_parameter.master_slave_mode = DISABLE;timer0_init_parameter.trgo_selection = TIMER_TRI_OUT_SRC_RESET;hal_timer_init(&timer0_info,TIMER0,&timer0_init_parameter);timer0_output_compare_parameter.compare_mode = TIMER_OC_MODE_PWM1;timer0_output_compare_parameter.oc_pulse_value = 124;timer0_output_compare_parameter.oc_polarity = TIMER_OC_POLARITY_HIGH;timer0_output_compare_parameter.oc_idlestate = TIMER_OC_IDLE_STATE_LOW;timer0_output_compare_parameter.oc_shadow = TIMER_OC_SHADOW_DISABLE;timer0_output_compare_parameter.oc_fastmode = TIMER_OC_FAST_DISABLE;timer0_output_compare_parameter.oc_clearmode = TIMER_OC_CLEAR_ENABLE;hal_timer_output_compare_config(&timer0_info,TIMER_CH_0,&timer0_output_compare_parameter);timer0_clear_source_parameter.clear_source = TIMER_OCPRE_CLEAR_SOURCE_CLR;hal_timer_ocpre_clear_source_config(&timer0_info,&timer0_clear_source_parameter);timer0_break_parameter.run_offstate = TIMER_ROS_STATE_DISABLE;timer0_break_parameter.idel_offstate = TIMER_IOS_STATE_DISABLE;timer0_break_parameter.break_polarity = TIMER_BREAK_POLARITY_HIGH;timer0_break_parameter.output_autostate = TIMER_OUTAUTO_DISABLE;timer0_break_parameter.protect_mode = TIMER_CCHP_PROT_OFF;timer0_break_parameter.break_state = TIMER_BREAK_DISABLE;hal_timer_break_config(&timer0_info,&timer0_break_parameter);/* user code [timer0_init local 1] begin */// Prescaler value = 107 = 108MHZ / (107 + 1) = 1MHZ// 不理会“Clock division” !!!// TIMER0实际执行时钟的周期 = (1 / 1MHZ)s = (1 / 1000,000)s = 0.000001s = 1us 一个TIMER0时钟周期 = 1us// 4KHZ的周期 = (1 / 4000)s = 0.00025s = 250 us// 那么4KHZ的PWM波的时钟(TIMER0实际执行时钟的周期)个数 = 250us / 1us = 250个计数 => 自动重装值 = (250 - 1)= 249// 驱动无源蜂鸣器的PWM波占空比要求是50%, 那么PWM波的比较值 = 250个 * 50% = 125个计数 => CMP比较值 = (125 - 1) = 124/* user code [timer0_init local 1] end */
}
实验结果和官方给的蜂鸣器频率响应曲线基本一样
只实验到了PWM = 4KHZ,确实声音是最大的,但是离近了(300mm)听,有点刺耳。
当PWM = 1.8KHZ时,声音虽然小了点,但是声音听起来舒服,不刺耳。
看官方推荐,2KHZ的声音样本比较悦耳。
再去找找,看有没有工业级别的2KHZ压电无源蜂鸣器。
看看实际波形
示波器夹子,一端在GND, 另一端在蜂鸣器2脚
看到PWM频率为4KHZ
波形幅度为2.44V
波形也不是方波,而是三角波。
前面失败图,波形不是这种三角波。波形幅度差不多。
是不是没有在蜂鸣器两边并联1K电阻引起的。等后续有时间再实验。
如果能用MOS来控制蜂鸣器,我还是倾向于用MOS来控制。