3. PWM呼吸灯
任务目标
使用ESP32内置的LEDC(LED Control)PWM模块,通过改变PWM占空比控制LED亮度,实现从暗到亮再到暗的呼吸灯效果。通过本案例理解PWM调光的基本原理与ESP32 LEDC的配置方法。
硬件与接线
- ESP32开发板 × 1
- LED(普通5mm或贴片均可)× 1
- 限流电阻 220Ω × 1
- 面包板与跳线若干
接线方式:将LED阳极(长脚)串联220Ω电阻后连接至GPIO2,LED阴极(短脚)接GND。GPIO2为ESP32板载LED常用引脚,也可换用其他可用GPIO。
PWM与LEDC原理简述
PWM(脉冲宽度调制)通过固定频率下改变高电平占空比来调节LED的平均电流,从而控制亮度。ESP32的LEDC模块提供16个通道(0~15),可绑定任意GPIO,支持配置PWM频率与分辨率(1~16位)。本案例使用8位分辨率(占空比0~255),频率5kHz(对LED无频闪感)。
完整代码
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"
#include "esp_err.h"
#define LED_GPIO 2
#define LEDC_MODE LEDC_LOW_SPEED_MODE
#define LEDC_CHANNEL LEDC_CHANNEL_0
#define LEDC_TIMER LEDC_TIMER_0
#define PWM_FREQ_HZ 5000
#define PWM_RES_BITS 8 // 8位分辨率,占空比0~255
#define DUTY_MAX ((1 << PWM_RES_BITS) - 1) // 255
#define STEP_DELAY_MS 10 // 每步延时(毫秒)
void app_main(void)
{
// 1. 配置LEDC定时器
ledc_timer_config_t timer_conf = {
.speed_mode = LEDC_MODE,
.timer_num = LEDC_TIMER,
.duty_resolution = PWM_RES_BITS,
.freq_hz = PWM_FREQ_HZ,
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&timer_conf));
// 2. 配置LEDC通道并绑定GPIO
ledc_channel_config_t channel_conf = {
.gpio_num = LED_GPIO,
.speed_mode = LEDC_MODE,
.channel = LEDC_CHANNEL,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER,
.duty = 0,
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&channel_conf));
// 3. 呼吸灯主循环:渐亮→渐暗
while (1) {
// 渐亮:占空比从0增加到255
for (int duty = 0; duty <= DUTY_MAX; duty++) {
ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, duty));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));
vTaskDelay(pdMS_TO_TICKS(STEP_DELAY_MS));
}
// 渐暗:占空比从255减小到0
for (int duty = DUTY_MAX; duty >= 0; duty--) {
ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, duty));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));
vTaskDelay(pdMS_TO_TICKS(STEP_DELAY_MS));
}
}
}
编译与烧录
本案例基于ESP-IDF开发框架(v5.x)。在项目目录下创建上述代码为 main.c,并确保 CMakeLists.txt 中已注册main组件。然后执行:
idf.py set-target esp32
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor
将 /dev/ttyUSB0 替换为实际串口设备名(Windows下为 COMx)。
验证方法
- 观察LED是否呈现周期性由暗到亮、再由亮到暗的平滑渐变,周期约为
256×2×10ms ≈ 5.1秒。 - 若LED不亮,检查GPIO2接线方向与电阻连接;若亮度跳变而非渐变,检查
STEP_DELAY_MS是否过小导致变化过快。 - 可通过调整
STEP_DELAY_MS改变呼吸速度,或修改PWM_RES_BITS改变亮度级数(如改为10位则占空比上限为1023,需同步修改循环边界)。
常见问题
- 编译报错找不到ledc头文件:确认在ESP-IDF环境下编译,且
driver/ledc.h路径正确。 - LED亮度无变化:检查GPIO是否被其他功能占用(如板载LED可能连接Flash),换用GPIO4、GPIO5等空闲引脚测试。
- 闪烁而非渐变:PWM频率过低(如低于1kHz)会产生可见闪烁,确认
PWM_FREQ_HZ设置为5000。