一、ESP32配置PWM实现呼吸灯
#define LED_PIN GPIO_NUM_27
void led_pwm_task(void *pvParameters)
{
// 配置LEDC定时器
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_13_BIT, // 设置PWM占空比分辨率为13位
.freq_hz = 5000, // PWM频率5KHz
.speed_mode = LEDC_HIGH_SPEED_MODE, // 高速模式
.timer_num = LEDC_TIMER_0 // 使用定时器0
};
ledc_timer_config(&ledc_timer);
// 配置LEDC通道
ledc_channel_config_t ledc_channel = {
.channel = LEDC_CHANNEL_0, // 使用LEDC通道0
.duty = 0, // 初始占空比为0(LED完全熄灭)
.gpio_num = LED_PIN, // 使用GPIO27引脚
.speed_mode = LEDC_HIGH_SPEED_MODE, // 使用高速模式
.timer_sel = LEDC_TIMER_0 // 使用定时器0
};
ledc_channel_config(&ledc_channel);
while(1) {
// 从0到最大亮度渐变
for(int duty = 0; duty < 8192; duty += 100) {
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, duty);
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
vTaskDelay(pdMS_TO_TICKS(10));
}
// 从最大亮度到0渐变
for(int duty = 8191; duty >= 0; duty -= 100) {
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, duty);
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
vTaskDelay(pdMS_TO_TICKS(10));
}
}
}
函数功能概述
led_pwm_task
函数是一个用于控制 LED 亮度渐变的 FreeRTOS 任务函数。它通过配置 ESP32 的 LEDC(LED 控制)模块,实现 LED 从暗到亮再从亮到暗的循环渐变效果。
函数内部代码详细解释
-
LEDC 定时器配置
ledc_timer_config_t ledc_timer
:定义一个 LEDC 定时器配置结构体变量。.duty_resolution = LEDC_TIMER_13_BIT
:设置 PWM 占空比分辨率为 13 位。这意味着占空比可以有 2^13 = 8192 个不同的步长,能够更精细地控制 LED 的亮度。占空比越大,LED 越亮。.freq_hz = 5000
:设置 PWM 频率为 5000Hz。这个频率决定了 PWM 信号每秒切换的次数,较高的频率可以使 LED 亮度变化更加平滑,一般人眼对这个频率的 PWM 信号闪烁不太敏感。.speed_mode = LEDC_HIGH_SPEED_MODE
:选择高速模式。LEDC 有两种速度模式,高速模式和低速模式,这里选择高速模式通常用于对时间精度要求较高的场景。.timer_num = LEDC_TIMER_0
:指定使用定时器 0。ESP32 的 LEDC 模块有多个定时器可供选择,这里选择定时器 0 来为后续的 LEDC 通道提供时钟源。然后调用ledc_timer_config(&ledc_timer)
函数应用这个定时器配置。
-
LEDC 通道配置
ledc_channel_config_t ledc_channel
:定义一个 LEDC 通道配置结构体变量。.channel = LEDC_CHANNEL_0
:选择通道 0。LEDC 有多个通道,每个通道可以连接到不同的 GPIO 引脚来控制不同的 LED 或者其他设备。.duty = 0
:初始占空比设置为 0,即 LED 初始状态为关闭。.gpio_num = LED_PIN
:指定用于控制 LED 的 GPIO 引脚,这里假设LED_PIN
已经定义为某个具体的 GPIO 引脚编号,比如 27。.speed_mode = LEDC_HIGH_SPEED_MODE
:同样选择高速模式,与定时器的速度模式保持一致。.timer_sel = LEDC_TIMER_0
:选择定时器 0 为这个通道的时钟源,与之前配置的定时器相匹配。接着调用ledc_channel_config(&ledc_channel)
函数完成通道配置。
-
LED 亮度渐变循环
-
while(1)
:进入无限循环,持续执行亮度渐变操作。-
从暗到亮渐变 :
for(int duty = 0; duty < 8192; duty += 100)
:从占空比 0 开始,每次增加 100,直到占空比达到 8191(因为 13 位分辨率最大值是 8191)。这里 8192 是 2^13,所以循环条件是duty < 8192
。ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, duty)
:设置通道 0 的占空比为当前duty
值,从而逐渐增加 LED 的亮度。ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0)
:更新占空比,使新的占空比设置生效。vTaskDelay(pdMS_TO_TICKS(10))
:任务延迟 10 毫秒,控制渐变速度,让亮度变化能够被肉眼观察到。
-
从亮到暗渐变 :
for(int duty = 8191; duty >= 0; duty -= 100)
:从占空比 8191 开始,每次减少 100,直到占空比达到 0。ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, duty)
:设置通道 0 的占空比为当前duty
值,逐渐降低 LED 的亮度。ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0)
:更新占空比。vTaskDelay(pdMS_TO_TICKS(10))
:同样任务延迟 10 毫秒,保持渐变速度一致。
-
-
这个循环使得 LED 不断地进行亮度的渐变,产生呼吸灯般的效果。
-
二、其他可用的 LEDC 配置选项
1. 占空比分辨率(duty_resolution
)
- 作用:决定 PWM 信号占空比的精度,值越大,亮度控制越精细,亮度的等级更丰富。
- 可选值:范围从
LEDC_TIMER_1_BIT
(1位,占空比0-1)到LEDC_TIMER_16_BIT
(16位,占空比0-65535)。常选LEDC_TIMER_13_BIT
(13位,占空比0-8191),适合多数LED调光场景。
2. PWM频率(freq_hz
)
- 作用:设置PWM信号频率,影响LED闪烁速度。
- 可选值:任意正整数,如1000Hz、5000Hz、10000Hz等。低频(如1000Hz)易闪烁,高频(5000Hz以上)更平滑,但需考虑硬件限制。
3. 速度模式(speed_mode
)
- 作用:选择LEDC工作模式,影响时钟源和性能。
- 可选值:
LEDC_HIGH_SPEED_MODE
(高速模式,适合高精度场景)、LEDC_LOW_SPEED_MODE
(低速模式,适合对时间精度要求低的场景)。
4. 定时器选择(timer_num
)
- 作用:选择生成PWM信号的定时器。
- 可选值:
LEDC_TIMER_0
、LEDC_TIMER_1
、LEDC_TIMER_2
、LEDC_TIMER_3
。不同定时器可独立配置频率和分辨率,支持多路PWM信号。
5. 通道选择(channel
)
- 作用:选择控制特定GPIO引脚的LEDC通道。
- 可选值:
LEDC_CHANNEL_0
、LEDC_CHANNEL_1
、LEDC_CHANNEL_2
、LEDC_CHANNEL_3
。每个通道可连接不同GPIO引脚,实现多路独立PWM输出。
6. GPIO引脚(gpio_num
)
- 作用:指定PWM信号输出的GPIO引脚。
- 可选值:ESP32支持的任一GPIO引脚(如GPIO2、GPIO4、GPIO12等)。需确保引脚支持LEDC功能,参考ESP32数据手册。
7. 初始占空比(duty
)
- 作用:设置通道初始占空比,决定LED初始亮度。
- 可选值:
0
(关闭)到最大值(由duty_resolution
决定,如13位为8191)。如duty=4096
,在13位分辨率下约为50%亮度。
8. 定时器绑定(timer_sel
)
- 作用:将通道绑定到指定定时器。
- 可选值:
LEDC_TIMER_0
、LEDC_TIMER_1
、LEDC_TIMER_2
、LEDC_TIMER_3
。需与定时器配置中的timer_num
一致,确保通道使用正确时钟源。