【PWM】无源蜂鸣器
下载例程代码: 下载代码
请一定按照 例程使用方法 🔗 导入例程,否则下载的可能不是例程而是其他工程。
PWM 简介
PWM 波形
PWM 波形是一种方波信号,是高/低电平不断切换的结果,其波形如图所示,这是 3 种占空比不同的波形:

PWM 的几个关键参数为:
- 频率(Frequency):即高低电平切换的速度,切换的速度越快则频率越高,1000Hz 的 PWM 波意味着 1 秒钟有 1000 个脉冲
- 占空比(Duty Cycle):即每个周期内,高电平所占的宽度
- 例如图中
50% duty cycle,即高/低电平的时间各占 50%; - 图中的
75% duty cycle,高电平占 75%,低电平占 25%; - 图中的
25% duty cycle,高电平占 25%,低电平占 75%;
- 例如图中
PWM 播放音调
通过改变PWM 频率,可以输出不同频率的方波信号。用这个信号驱动无源蜂鸣器,便能播放不同频率的声音。
无源蜂鸣器原理
- 学习板上的蜂鸣器型号为**:QMB-09B-03 电磁式无源蜂鸣器**。
- 蜂鸣器内部有一个 电磁线圈,能够驱动 振动膜片 发出声音。通过 PWM 给蜂鸣器提供不同频率的信号,即可发出不同频率的声音
- 实际操作中,除了控制 PWM 频率,还需要控制 PWM 占空比,以使膜片振动趋近于正弦波,从而发出清脆明亮的声音。在学习板上,使用 20%占空比 可以有较好的响度和音质

如何使用例程
下载程序,即可看到效果
程序效果
- 烧录例程后,按下 KEY1、KEY2 会听到 2kHz、3kHz 的音调
- 可以尝试修改例程代码,产生其他频率的声音
例程讲解
下面介绍了如何自己实现该例程的功能
1、工程配置
- 开启外部晶振:在 Pinout&Configuration -> System Core -> RCC 页面,将 High Speed Clock (HSE) 配置为 Crystal/Ceramic Resonator

- 配置时钟频率:在 Clock Configuration 页面,将 PLL Source 选择为 HSE,将 System Clock Mux 选择为 PLLCLK,然后在 HCLK (MHz) 输入 72 并回车,将 HCLK 频率配置为 72 MHz

-
分配引脚:在 Pinout&Configuration 页面,配置如下引脚
-
将 PB9 配置为 TIM4_CH4,
-
将 PB12、PB13 设置为 GPIO_Input,并分别设置 User Label 为 KEY1、KEY2
-
-
配置 GPIO:在 Pinout&Configuration -> GPIO,将 PB13 的 GPIO Pull-up/Pull-down 配置为 Pull-up
-
配置 TIM4:在 Pinout&Configuration -> Timers -> TIM4
-
勾选 Internal Clock,开启 TIM4 的内部时钟源
-
Configuration -> Mode,将 Channel4 配置为 PWM Generation CH4
-
Configuration -> Parameter Settings -> Counter Settings,将 Prescaler 配置为 72-1
-
2、代码
-
启动 PWM 输出
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4); -
在 while 循环中检测按键并输出相应的频率
-
htim4.Instance->ARR = 500可以将 TIM4 的 Counter Period 设置为 500此时,PWM 频率 = 72 MHz ÷ 72 ÷ 500 = 2 kHz
-
__HAL_TIM_SET_COMPARE可以设置 PWM 的占空比,将占空比设为 20%,可以确保声音清脆明亮注意:占空比必须小于前面配置的Counter Period,例程中配置为 100-1,即占空比可调范围是 0 - 99
while (1)
{
// KEY1按下: 输出2kHz声波
if (!HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin))
{
htim4.Instance->ARR = 500; // 2kHz = 72MHz / 72 / 500
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_4, htim4.Instance->ARR / 5); // 20%占空比
}
// KEY2按下: 输出3kHz声波
else if (!HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin))
{
htim4.Instance->ARR = 334; // 3kHz = 72MHz / 72 / 334
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_4, htim4.Instance->ARR / 5); // 20%占空比
}
// 否则: 关闭声波输出
else
{
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_4, 0);
}
HAL_Delay(100);
} -