ESP32中LED_PWM控制器

背景

ESP32想做个typeC充电时呼吸灯的应用,看了开发手册发现带有个LED PWM控制器,可以无需处理器干预实现硬件的PWM脉宽的自由步进,从而实现呼吸灯渐变的效果,主要参考了官方的资料,把调试的过程记录下来
如有异议,欢迎留言指正

概述

LED PWM 控制器主要用于控制 LED,也可产生 PWM 信号用于其他设备的控制。LED_PWM控制器总共有16路通道,分为8路高速通道和8路低速通道,可以产生独立的波形来驱动 RGB LED 设备等。

LED PWM控制器最大可生成40MHz的频率,此时占空比分辨率为1,也就是50%固定脉宽;20Mhz时,占空比分辨率为3

LED PWM 控制器的高速通道和低速通道均支持硬件渐变功能【高低速定时器】,可在无需 CPU 干预的情况下自动改变 PWM 信号的占空比,也可由软件改变 PWM 信号的占空比,实现亮度和颜色渐变。此外,低速通道在 Sleep 模式下仍可运行。

架构

LED_PWM架构:4个高速定时器与4个低速定时器分别对应8个高速通道与8个低速通道
ESP32中LED_PWM控制器_第1张图片

LED_PWM通道图
ESP32中LED_PWM控制器_第2张图片

  • 时钟源选择器可以选择两个时钟源,分别是APB_CLK【由CPU_CLK产生】和REF_TICK【由APB_CLK分频产生】,下一期会单独讲下ESP32系统时钟树

  • 时钟通过18bit的分配器进行分频,计算公式LEDC_DEV_CLK = A*B/256,A代表高10bit整数部分,B代表低8位小数部分
    在这里插入图片描述

  • 分配器的输出时钟作为计数器的基准时钟,计数器最大有效位为20bit,计数达到2^ LEDC_HSTIMERx_DUTY_RES – 1时,会产生溢出中断;溢出后计数值回滚到0,这也就决定了PWM通道的频率

  • 输出频率的计算公式【由分频系数、计数器参与决定】
    在这里插入图片描述

低速通道与高速通道有两个区别

  • 高速定位器的时钟源采用了 REF_TICK 或 APB_CLK,低速定位器采用了 REF_TICK 或 SLOW_CLOCK。置位 LEDC_APB_CLK_SEL 寄存器,SLOW_CLOCK 的频率为 80 MHz,否则为 8 MHz。
  • 当软件修改了高速通道计数器的最大值或分频系数的话,输出信号的更新将会在下一次溢出中断之后生效。而低速通道在置位LEDC_LSTIMERx_PARA_UP 之后,立刻更新计数器的计数范围参数和分频器的分频系数。

通道

从通道图中不难发现,每个通道都有两个比较器,分别为high_level_comparatorlow_level_comparator

  • high_level_comparator:比较值是hpoint,当计数器的值达到hpiot时,输出高电平
  • low_level_comparator:比较值是lpoint,当计数器的值等于lpiot时,输出低电平
    ESP32中LED_PWM控制器_第3张图片

寄存器

  • LEDC_CONF_REG:用于设置 SLOW_CLK 的频率【0 - 8MHz】【1 - 80MHz】
  • LEDC_HSCHn_CONF0_REG:选择高速定时器【0 - 3】与使能通道控制
  • LEDC_HSCHn_CONF1_REG:高速通道递增递减的占空比与步进的步长值
  • LEDC_HSCHn_DUTY_REG:控制输出占空比,配置LPOINT与HPOINT
  • LEDC_HSTIMERx_CONF_REG:选择高速时钟APB_CLKREF_TICK与计数范围、分频系数
  • LEDC_DUTY_CHNG_END_LSCHn_INT: 低速通道上的占空比渐变结束触发中断
  • LEDC_DUTY_CHNG_END_HSCHn_INT: 高速通道上的占空比渐变结束触发中断
  • LEDC_HS_TIMERn_OVF_INT: 高速时钟计数器达到最大计数值触发中断
  • LEDC_LS_TIMERn_OVF_INT: 低速时钟计数器达到最大计数值触发中断

常用API

打开idf目录下的ledc.h,路径esp-idf\components\driver\include\driver

  • ledc_channel_config:LEDC通道配置,参数中ledc_channel_config_t主要设置通道、输出GPIO、速度模式、定时器、占空比
  • ledc_timer_config:定时器配置,参数ledc_timer_config_t主要设置频率、占空比分辨率、所选的定时器
  • ledc_set_duty:设置新的占空比,配置完成后需要调用ledc_update_duty使其更新生效
  • ledc_fade_func_install:安装渐变功能服务,应用中如果需要PWM自动渐变时必须调用
  • ledc_set_fade_with_time:指定通道与设置期望占空比,渐变功能在指定的时间内完成
  • ledc_set_fade_with_step:指定通道与目标占空比,渐变功能在指定的周期个数内按照步进的单位完成
  • ledc_fade_start:开始运行渐变的功能

应用实例

打开idf目录下的test_ledc.c,路径esp-idf\components\driver\test
摘取一段通过指定时间渐变的代码进行讲解,其他代码可以自行展开引用

  • 例程中配置PULSE_IO为输出IO口,5KHz的频率,实现1秒的渐变亮,1秒渐变暗的效果
TEST_CASE("LEDC fade with time(logic analyzer)", "[ledc][test_env=UT_T1_LEDC]")
{
     
#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
    return;
#endif

#ifdef CONFIG_IDF_TARGET_ESP32
    const ledc_mode_t test_speed_mode = LEDC_HIGH_SPEED_MODE;
#elif defined CONFIG_IDF_TARGET_ESP32S2
    const ledc_mode_t test_speed_mode = LEDC_LOW_SPEED_MODE;
#endif
    ledc_channel_config_t ledc_ch_config = {
     
        .gpio_num = PULSE_IO,//gpio
        .speed_mode = test_speed_mode,//模式
        .channel  = LEDC_CHANNEL_0,//通道
        .intr_type = LEDC_INTR_DISABLE,//禁用中断
        .timer_sel = LEDC_TIMER_0,//time0
        .duty = 0,//占空比0
        .hpoint = 0,//高电平比较
    };
    TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));//配置通道

    ledc_timer_config_t ledc_time_config = {
     
        .speed_mode = test_speed_mode,//模式
        .duty_resolution = LEDC_TIMER_13_BIT,//13位分辨率
        .timer_num = LEDC_TIMER_0,//定时器0
        .freq_hz = 5000,//5khz
        .clk_cfg = LEDC_USE_APB_CLK,//时钟源
    };
    TEST_ESP_OK(ledc_timer_config(&ledc_time_config));//定时器配置

    //initialize fade service
    TEST_ESP_OK(ledc_fade_func_install(0));//安装服务

    TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 1000));//1s 4000目标占空比渐变
    TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));//开始运行
    vTaskDelay(1000 / portTICK_RATE_MS);
    TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 4000);//确认当前占空比

    TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 0, 1000));//1s 占空比0
    TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));//开始运行
    vTaskDelay(1000 / portTICK_RATE_MS);
    TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 0);//确认当前占空比

    //deinitial fade service
    ledc_fade_func_uninstall();//卸载服务,释放ram
}

抓取波形
ESP32中LED_PWM控制器_第4张图片

API文档

PS:总体来说配置相对简单,在一些特定的应用场景下,也可以通过该控制器输出时钟源给外设使用,如camera、RF相关的硬件外设,节省掉电路设计中的晶振的投入

你可能感兴趣的:(ESP32,ESP32,LEDPWM,呼吸灯)