跳到主要内容

【PWM】无源蜂鸣器

下载例程代码下载代码

注意

请一定按照 例程使用方法 🔗 导入例程,否则下载的可能不是例程而是其他工程。

PWM 简介

PWM 波形

PWM 波形是一种方波信号,是高/低电平不断切换的结果,其波形如图所示,这是 3 种占空比不同的波形:

PWM波形

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);
    }