案例分析
实质上就是调整PWM占空比调节灯的亮度,
概述
LED Controller (led控制器)控制LED,也可以产生PWM信号用于控制其他设备,
该控制器有 6个通道,可独立产生波形来驱动RGB LED设备
LED PWM 控制器可在无需CPU干扰的情况下自动改变占空比,实现亮度和颜色。
使用LEDC记得加头文件
#include "driver/ledc.h"
功能概述
设置LEDC 通道分为三个步骤(!!!!esp32-C3只支持设置通道为低速)
1. 定时器配置 指定PWM信号的频率 和 占空比
2.通道配置 绑定控制器和输出PWM信号的GPIO
3.改变PWM信号 输出PWM信号驱动LED
定时器配置
首次 LEDC 配置时,建议先配置定时器(调用函数 ledc_timer_config()),再配置通道(调用函数 ledc_channel_config())。这样可以确保 IO 脚上的 PWM 信号自有输出开始其频率就是正确的。
要设置定时器,可调用函数 ledc_timer_config(),并将包括如下配置参数的数据结构 ledc_timer_config_t 传递给该函数:
-
速度模式(值必须为
LEDC_LOW_SPEED_MODE
) -
定时器索引 ledc_timer_t
-
PWM 信号频率(Hz)
-
PWM 占空比分辨率
-
时钟源 ledc_clk_cfg_t
频率和占空比分辨率相互关联。PWM 频率越高,占空比分辨率越低,反之亦然。如果 API 不是用来改变 LED 亮度,而是用于其它目的,这种相互关系可能会很重要。更多信息详见 频率和占空比分辨率支持范围 一节。
时钟源同样可以限制PWM频率。选择的时钟源频率越高,可以配置的PWM频率上限就越高。
时钟名称 | 时钟频率 | 时钟功能 |
---|---|---|
APB_CLK | 80 MHz | / |
RC_FAST_CLK | ~20 MHz | 支持动态调频(DFS)功能,支持Light-sleep模式 |
XTAL_CLK | 40 MHz | 支持动态调频(DFS)功能 |
备注
-
如果 ESP32-C3 的定时器选用了RC_FAST_CLK作为其时钟源,驱动会通过内部校准来得知这个时钟源的实际频率。这样确保了输出PWM信号频率的精准性。
-
ESP32-C3 的所有定时器共用一个时钟源。因此 ESP32-C3 不支持给不同的定时器配置不同的时钟源
当一个定时器不再被任何通道所需要时,可以通过调用相同的函数 ledc_timer_config() 来重置这个定时器。此时,函数入参的配置结构体需要指定:
-
ledc_timer_config_t::speed_mode 重置定时器的所属速度模式 (ledc_mode_t)
-
ledc_timer_config_t::timer_num 重置定时器的索引 (ledc_timer_t)
-
ledc_timer_config_t::deconfigure 将指定定时器重置必须配置此项为 true
通道配置
定时器设置好后,请配置所需的通道(ledc_channel_t 之一)。配置通道需调用函数 ledc_channel_config()。
通道的配置与定时器设置类似,需向通道配置函数传递包括通道配置参数的结构体 ledc_channel_config_t 。
此时,通道会按照 ledc_channel_config_t 的配置开始运作,并在选定的 GPIO 上生成由定时器设置指定的频率和占空比的 PWM 信号。在通道运作过程中,可以随时通过调用函数 ledc_stop() 将其暂停。
改变 PWM 信号
通道开始运行、生成具有恒定占空比和频率的 PWM 信号之后,有几种方式可以改变该信号。驱动 LED 时,主要通过改变占空比来变化光线亮度。
以下两节介绍了如何使用软件和硬件改变占空比。如有需要,PWM 信号的频率也可更改,详见 改变 PWM 频率 一节。
备注
在 ESP32-C3 的 LED PWM 控制器中,所有的定时器和通道都只支持低速模式。对 PWM 设置的任何改变,都需要由软件显式地触发(见下文)。
使用软件改变 PWM 占空比
调用函数 ledc_set_duty() 可以设置新的占空比。之后,调用函数 ledc_update_duty() 使新配置生效。要查看当前设置的占空比,可使用 _get_
函数 ledc_get_duty()。
另外一种设置占空比和其他通道参数的方式是调用 通道配置 一节提到的函数 ledc_channel_config()。
传递给函数的占空比数值范围取决于选定的 duty_resolution
,应为 0
至 (2 ** duty_resolution) - 1
。例如,如选定的占空比分辨率为 10,则占空比的数值范围为 0 至 1023。此时分辨率为 ~0.1%。
实现
#include <stdio.h>
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define LED_PIN GPIO_NUM_13
void led_pwm_Init();
void app_main(void)
{
led_pwm_Init();
while (1)
{
/* code */
for (int duty = 0; duty <= 255; duty++)
{
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty); //设置新的占空比
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); //更新配置
vTaskDelay(pdMS_TO_TICKS(10));
}
for (int duty = 255; duty >= 0; duty--)
{
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
vTaskDelay(pdMS_TO_TICKS(10));
}
}
}
void led_pwm_Init()
{
// 配置定时器
ledc_timer_config_t ledc_timer =
{
.duty_resolution = LEDC_TIMER_10_BIT, //PWM占空比分辨率
.freq_hz = 5000, //PWM 信号频率
.speed_mode = LEDC_LOW_SPEED_MODE, // 定时器速度模式
.timer_num = LEDC_TIMER_0, // 定时器索引
// .clk_cfg = LEDC_AUTO_CLK //时钟源
};
ledc_timer_config(&ledc_timer);
// 配置通道
ledc_channel_config_t ledc_channel =
{
.channel = LEDC_CHANNEL_0, //LEDC通道
.duty = 0, //PWM信号占空比
.gpio_num = LED_PIN, //GPIO
.speed_mode = LEDC_LOW_SPEED_MODE, //定时器模式(esp32c3只支持低速) LEDC_HIGH_SPEED_MODE
.timer_sel = LEDC_TIMER_0 //定时器选择
};
ledc_channel_config(&ledc_channel);
}