Skip to content

第 2 章:无源蜂鸣器(LEDC PWM 音调控制)

📂 示例代码02_buzzer

2.1 知识要点

  • LEDC(LED Control)外设的定时器与通道配置
  • 通过动态修改 PWM 频率实现音调变化
  • 占空比与音量的关系(50% 占空比驱动无源蜂鸣器)
  • 音符频率表与旋律播放逻辑

2.2 课程内容

无源蜂鸣器需要外部提供特定频率的方波才能发声,频率决定音调。ESP32-S3 的 LEDC 外设可以灵活配置 PWM 频率,非常适合驱动蜂鸣器播放旋律。本章实现 C 大调音阶的上行与下行演奏。

2.3 基础学习

LEDC 外设结构

LEDC 包含 4 个定时器和 8 个通道(低速模式):

  • 定时器:配置时钟源、分辨率(bit 数)、频率
  • 通道:绑定到定时器,配置 GPIO 和占空比

蜂鸣器使用 LEDC_TIMER_1,10-bit 分辨率(1024 步),占空比 512(50%)时输出对称方波。

改变音调只需调用 ledc_set_freq(),无需重新初始化通道。静音时将占空比置 0。

音符频率(Hz)

C4=262  D4=294  E4=330  F4=349
G4=392  A4=440  B4=494  C5=523

2.4 程序学习

初始化定时器与通道:

c
ledc_timer_config_t timer = {
    .speed_mode      = LEDC_LOW_SPEED_MODE,
    .duty_resolution = LEDC_TIMER_10_BIT,
    .timer_num       = LEDC_TIMER_1,
    .freq_hz         = 1000,
    .clk_cfg         = LEDC_AUTO_CLK,
};
ledc_timer_config(&timer);

ledc_channel_config_t ch = {
    .gpio_num   = 42,
    .speed_mode = LEDC_LOW_SPEED_MODE,
    .channel    = LEDC_CHANNEL_2,
    .timer_sel  = LEDC_TIMER_1,
    .duty       = 0,
};
ledc_channel_config(&ch);

播放单个音符(非阻塞,esp_timer 异步关闭):

c
static esp_timer_handle_t s_buzzer_timer = NULL;

static void buzzer_set_off(void)
{
    ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2, 0);
    ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2);
}

static void buzzer_timer_cb(void *arg) { buzzer_set_off(); }

static void buzzer_tone(uint32_t freq_hz, uint32_t duration_ms)
{
    if (freq_hz == 0 || duration_ms == 0) { buzzer_set_off(); return; }
    if (s_buzzer_timer == NULL) {
        esp_timer_create_args_t args = { .callback = buzzer_timer_cb, .name = "buzzer" };
        esp_timer_create(&args, &s_buzzer_timer);
    }
    esp_timer_stop(s_buzzer_timer);
    ledc_set_freq(LEDC_LOW_SPEED_MODE, LEDC_TIMER_1, freq_hz);
    ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2, 512); /* 50% duty */
    ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2);
    /* 到期后由定时器回调异步关闭,不阻塞调用任务 */
    esp_timer_start_once(s_buzzer_timer, (uint64_t)duration_ms * 1000);
}

关键点:旧版用 vTaskDelay 阻塞等待音符结束,新版改用 esp_timer_start_once 启动一次性定时器,到期后回调自动将占空比置 0。调用方在 buzzer_tone 返回后可以立即执行其他逻辑,音符播放完全异步。

2.5 课程总结

本章学会了使用 LEDC 外设驱动无源蜂鸣器,掌握了通过动态修改频率实现音调控制的方法。LEDC 是 ESP32-S3 上最通用的 PWM 外设,后续章节的 ESC 和舵机控制也将使用它。


Built for OSRCORE robot development board.