蜂鸣器开发笔记

1. 蜂鸣器类型

常用的蜂鸣器类型主要分为两类。

  • 有源蜂鸣器,内置震荡电路,固定频率(固定音调)。依靠高低电平驱动。可以播放简单提示音。
  • 无源蜂鸣器,五震荡电路,依靠PWM驱动。可以播放旋律。

有源蜂鸣器通常比无源蜂鸣器便宜约20%-50%,通常尺寸越大越贵,普通蜂鸣器均价在8毛左右。

典型蜂鸣器工作范围大概在500Hz - 5kHz。

无源蜂鸣器频率与音高的关系:频率越高,声音越尖锐。本人对音乐没有什么造诣,很难分辨哆来咪发唆,感觉差不太多。

2. 无源蜂鸣器控制

控制要点:通过不同的PWM频率来调整音高,占空比用50%即可。

关键在于重装载值的计算,根据目标频率反推计算重装载值(ARR)

  • 计算PWM频率 = 时钟频率 / (预分频 × ARR)
  • 占空比 = CRR / ARR = 50%
/**
 * @brief 计算TIM3的ARR值(自动重装载值)
 * @param u16FreqHz 目标频率(Hz)
 * @return ARR值,0表示频率超出范围
 */
static uint16_t BspBeepCalculateArr(uint16_t u16FreqHz)
{
    uint32_t u32Arr;

    if (u16FreqHz < BEEP_FREQ_MIN || u16FreqHz > BEEP_FREQ_MAX) {
        return 0;
    }

    // 计算公式:ARR = (Fpclk / (预分频 * 频率)) - 1
    // Fpclk = 48MHz, 预分频 = 1
    u32Arr = (SYSTEM_CLOCK_FREQ / u16FreqHz) - 1;

    // ARR必须是16位无符号整数
    if (u32Arr > 0xFFFF) {
        return 0;
    }

    return (uint16_t)u32Arr;
}

/**
 * @brief 设置蜂鸣器频率
 * @param u16FreqHz 目标频率(Hz),范围:500-8000Hz
 * @note 频率设置立即生效,但不会自动启动蜂鸣器
 */
void BspBeepSetFrequency(uint16_t u16FreqHz)
{
    uint16_t u16Arr, u16Ccr;

    // 检查频率范围
    if (u16FreqHz < BEEP_FREQ_MIN || u16FreqHz > BEEP_FREQ_MAX) {
        LOG_WARN("Beep frequency %dHz out of range (%d-%d)",
                 u16FreqHz, BEEP_FREQ_MIN, BEEP_FREQ_MAX);
        return;
    }

    // 计算ARR和CCR值
    u16Arr = BspBeepCalculateArr(u16FreqHz);
    if (u16Arr == 0) {
        LOG_ERROR("Failed to calculate ARR for frequency %dHz", u16FreqHz);
        return;
    }

    u16Ccr = BspBeepCalculateCcr(u16Arr);

    // 保存频率
    s_stBeepCtrl.frequency = u16FreqHz;

    // 如果TIM3已经初始化,更新配置
    if (s_bTimer3Initialized) {
        bool wasActive = s_stBeepCtrl.isActive;

        // 如果正在响铃,先停止
        if (wasActive) {
            BspBeepOff();
        }

        // 重新配置TIM3
        BspTimer3Cfg(u16Arr, u16Ccr);

        // 如果之前正在响铃,重新启动
        if (wasActive) {
            BspBeepOn();
        }
    } else {
        // 首次配置TIM3
        BspTimer3Cfg(u16Arr, u16Ccr);
    }

    LOG_DEBUG("Beep frequency set to %dHz (ARR=0x%04X, CCR=0x%04X)",
              u16FreqHz, u16Arr, u16Ccr);
}

results matching ""

    No results matching ""