4. PWM调光LED
任务目标
使用ESP32-S3的LEDC模块生成PWM信号驱动LED,实现亮度从暗到亮再回到暗的平滑呼吸灯效果。通过本案例掌握LEDC通道配置、PWM频率与占空比调节方法。
硬件准备
- ESP32-S3开发板
- LED(建议串联220Ω限流电阻)
- 连接线:LED正极接GPIO48,负极经电阻接GND
核心代码
#include <stdio.h>
#include "driver/ledc.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define LED_GPIO 48
#define LEDC_TIMER LEDC_TIMER_0
#define LEDC_MODE LEDC_LOW_SPEED_MODE
#define LEDC_CHANNEL LEDC_CHANNEL_0
#define LEDC_DUTY_RES LEDC_TIMER_13_BIT // 分辨率:13位,占空比0~8191
#define LEDC_FREQ_HZ 5000 // PWM频率5kHz
static const char *TAG = "pwm_led";
void app_main(void)
{
// 1. 配置LEDC定时器
ledc_timer_config_t timer_conf = {
.speed_mode = LEDC_MODE,
.duty_resolution = LEDC_DUTY_RES,
.timer_num = LEDC_TIMER,
.freq_hz = LEDC_FREQ_HZ,
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&timer_conf));
// 2. 配置LEDC通道
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));
ESP_LOGI(TAG, "PWM呼吸灯启动,GPIO%d,频率%dHz", LED_GPIO, LEDC_FREQ_HZ);
uint32_t max_duty = (1 << 13) - 1; // 8191
uint32_t duty = 0;
int8_t step = 8; // 每次调整的占空比步长
while (1) {
// 3. 设置占空比并输出
ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, duty));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));
duty += step;
if (duty >= max_duty) {
duty = max_duty;
step = -step; // 到达最亮,开始变暗
} else if (duty == 0) {
step = -step; // 到达最暗,开始变亮
}
vTaskDelay(pdMS_TO_TICKS(10)); // 每10ms调整一次,完成一个周期约2秒
}
}
编译与烧录
- 在ESP-IDF环境中创建项目,将上述代码保存为
main/pwm_led.c,并确保main/CMakeLists.txt中已注册该源文件。 - 在项目根目录执行
idf.py set-target esp32s3设置目标芯片。 - 执行
idf.py build编译固件。 - 连接开发板,执行
idf.py -p /dev/ttyUSB0 flash monitor烧录并打开串口监视器(端口号按实际修改)。
验证方法
- 观察LED是否呈现周期性由暗到亮、再由亮到暗的呼吸效果,周期约2秒。
- 串口监视器应输出日志
PWM呼吸灯启动,GPIO48,频率5000Hz,无错误信息。 - 用示波器或逻辑分析仪测量GPIO48,可见频率约5kHz、占空比在0%~100%之间周期性变化的方波信号。
关键说明
- LEDC的13位分辨率对应占空比范围0~8191,
ledc_set_duty设置目标占空比后必须调用ledc_update_duty使配置生效。 - 步长8和延时10ms共同决定呼吸速度,调整这两个参数可改变渐变快慢。
- 若LED亮度变化不明显,可检查GPIO48是否支持LEDC输出(ESP32-S3大部分GPIO均可),并确认限流电阻连接正确。