没志青年
发布于 2025-07-28 / 24 阅读
0

ESP32 LED PWM 控制器(LEDC)

手册第35章,1231

LED PWM 控制器 - ESP32-S3 - — ESP-IDF 编程指南 v5.5 文档

LED 控制器 (LEDC) 主要用于控制 LED,也可产生 PWM 信号用于其他设备的控制。

S3 LEDC 特点:

  • 8 个PWM生成器,即8通道。

    • 高速通道:四个独立的定时器,可在无需 CPU 干预的情况下自动地改变 PWM 占空比。

    • 低速通道:在软件中实现。

  • 所有定时器使用同一个时钟源信号,每组通道都可以使用不同的定时器。

组成:

配置

官方文档提示:先配置定时器,再配置通道,以确保 IO 脚上的 PWM 信号自有输出开始其频率就是正确的。

定时器配置

// LEDC 定时器初始化    
ledc_timer_config_t ledc_timer = {
        .speed_mode       = LEDC_MODE,      // 低速模式
        .timer_num        = LEDC_TIMER,     // 定时器ID
        .duty_resolution  = LEDC_DUTY_RES,   // 占空比分辨率
        .freq_hz          = LEDC_FREQUENCY,  // PWM 频率
        .clk_cfg          = LEDC_AUTO_CLK    // 时钟源
    };
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

注意:

  • PWM 频率受时钟源的限制,时钟源频率越高,可以配置的 PWM 频率上限就越高。

  • 占空比分辨率和 PWM 频率的关系:

    • 分辨率越高,占空比可调节的档位就越多。

    • 当用于驱动 LED 时:PWM 频率设为 5 kHz 时,占空比分辨率最大可达 13 位。

    • 当需要生成频率较高的信号时:随着 PWM 频率的增加,分辨率必须降低,否则会硬件报错。

      • 最大频率为 40 MHz,占空比分辨率为 1 位,也就是说,占空比固定为 50%,无法调整。

      • 例如,频率为 20 MHz,占空比分辨率为 2 位,则占空比可选 25%、50%、75%

传入时钟源频率及期望的 PWM 信号频率,这个函数可以直接找到最大可配的占空比分辨率值:

uint32_t ledc_find_suitable_duty_resolution(uint32_t src_clk_freq, uint32_t timer_freq)

输出通道配置

// LEDC 输出通道初始化
ledc_channel_config_t ledc_channel = {
        .speed_mode     = LEDC_MODE,        // 低速模式
        .channel        = LEDC_CHANNEL,     // PWM 通道0-7
        .timer_sel      = LEDC_TIMER,       // 关联定时器,也就是上面初始化好的那个定时器
        .intr_type      = LEDC_INTR_DISABLE,// 不使能中断
        .gpio_num       = LEDC_OUTPUT_IO,   // 设置输出PWM方波的GPIO管脚
        .duty           = 0,                // 设置默认占空比为0
        .hpoint         = 0
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));

配置函数:动态生效的,无需暂停-配置-启动,直接配置。

函数

说明

esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t freq_hz)

设置频率

修改占空比

设置占空比:

esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty)

更新占空比:

esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel)

注意:

  • 更新后不会立即生效,当下一个 PWM 周期到达时才会生效。

  • ledc_set_duty、ledc_set_duty_with_hpoint、ledc_update_duty 这些函数是线程不安全的。

停止 LEDC

esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_lev

反初始化 LEDC

渐变功能

(1)开启渐变功能

esp_err_t ledc_fade_func_install(int intr_alloc_flags)

0:默认,自动选择合适的中断分配,最常用。

(2)配置渐变效果(在 ledc_fade_func_install() 后,在ledc_fade_start()后。)

esp_err_t ledc_set_fade_with_time( ledc_mode_t speed_mode,
                                   ledc_channel_t channel,
                                   uint32_t target_duty,      // 目标占空比,是数值,不是百分比
                                   int desired_fade_time_ms )  // 从当前占空比到目标占空比,期望多长时间

渐变效果手动控制:

esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, 
uint32_t target_duty,    // 目标占空比
uint32_t scale,          // 占空比每次变化多少
 uint32_t cycle_num)    // 一个占空比持续多少周期

(3)启动渐变

esp_err_t ledc_fade_start(ledc_mode_t speed_mode,
ledc_channel_t channel,
ledc_fade_mode_t fade_mode)

也可以用一个函数完成配置和启动:

esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t desired_fade_time_ms, ledc_fade_mode_t fade_mode)

渐变回调函数

渐变完成后会自己停止,在回调函数中可重新配置并开启。

回调函数禁止引起阻塞,只能调用 FreeRTOS 的 ISR 类型函数。