ESP32 LCD背光PWM控制全解析
#include "driver/ledc.h"
#include "esp_err.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <stdio.h>// 日志标签
static const char *TAG = "LCD_PWM";// PWM配置参数
#define LCD_BACKLIGHT_GPIO GPIO_NUM_5 // LCD背光引脚,根据实际硬件修改
#define LEDC_TIMER LEDC_TIMER_0 // 使用定时器0
#define LEDC_MODE LEDC_LOW_SPEED_MODE
#define LEDC_CHANNEL LEDC_CHANNEL_0 // 使用通道0
#define LEDC_DUTY_RES LEDC_TIMER_10_BIT // 10位分辨率(0-1023)
#define LEDC_FREQUENCY 5000 // 5kHz PWM频率/*** @brief 初始化PWM用于LCD背光控制** @return esp_err_t ESP_OK表示成功*/
esp_err_t lcd_backlight_init(void)
{// 配置LEDC定时器ledc_timer_config_t ledc_timer = {.speed_mode = LEDC_MODE,.timer_num = LEDC_TIMER,.duty_resolution = LEDC_DUTY_RES,.freq_hz = LEDC_FREQUENCY,.clk_cfg = LEDC_AUTO_CLK};esp_err_t ret = ledc_timer_config(&ledc_timer);if (ret != ESP_OK) {ESP_LOGE(TAG, "定时器配置失败: %s", esp_err_to_name(ret));return ret;}// 配置LEDC通道ledc_channel_config_t ledc_channel = {.speed_mode = LEDC_MODE,.channel = LEDC_CHANNEL,.timer_sel = LEDC_TIMER,.intr_type = LEDC_INTR_DISABLE,.gpio_num = LCD_BACKLIGHT_GPIO,.duty = 0, // 初始占空比为0(关闭).hpoint = 0};ret = ledc_channel_config(&ledc_channel);if (ret != ESP_OK) {ESP_LOGE(TAG, "通道配置失败: %s", esp_err_to_name(ret));return ret;}ESP_LOGI(TAG, "LCD背光PWM初始化成功");return ESP_OK;
}/*** @brief 根据百分比设置LCD背光亮度** @param brightness_percent 亮度百分比(0-100)* 0 = 完全关闭* 100 = 最大亮度* @return esp_err_t ESP_OK表示成功,ESP_ERR_INVALID_ARG表示参数无效*/
esp_err_t lcd_backlight_set_brightness(uint8_t brightness_percent)
{// 参数检查if (brightness_percent > 100) {ESP_LOGE(TAG, "亮度百分比无效: %d (应在0-100之间)", brightness_percent);return ESP_ERR_INVALID_ARG;}// 将百分比转换为占空比值 (0-1023)uint32_t duty = (brightness_percent * ((1 << LEDC_DUTY_RES) - 1)) / 100;// 设置占空比esp_err_t ret = ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, duty);if (ret != ESP_OK) {ESP_LOGE(TAG, "设置占空比失败: %s", esp_err_to_name(ret));return ret;}// 更新占空比ret = ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);if (ret != ESP_OK) {ESP_LOGE(TAG, "更新占空比失败: %s", esp_err_to_name(ret));return ret;}ESP_LOGI(TAG, "设置亮度为: %d%% (duty: %ld)", brightness_percent, duty);return ESP_OK;
}/*** @brief 平滑调节亮度(带淡入淡出效果)** @param target_percent 目标亮度百分比(0-100)* @param fade_time_ms 淡入淡出时间(毫秒)* @return esp_err_t ESP_OK表示成功*/
esp_err_t lcd_backlight_fade_to(uint8_t target_percent, uint32_t fade_time_ms)
{if (target_percent > 100) {ESP_LOGE(TAG, "目标亮度百分比无效: %d", target_percent);return ESP_ERR_INVALID_ARG;}uint32_t target_duty = (target_percent * ((1 << LEDC_DUTY_RES) - 1)) / 100;// 设置淡入淡出esp_err_t ret = ledc_set_fade_with_time(LEDC_MODE, LEDC_CHANNEL,target_duty, fade_time_ms);if (ret != ESP_OK) {ESP_LOGE(TAG, "设置淡入淡出失败: %s", esp_err_to_name(ret));return ret;}// 启动淡入淡出ret = ledc_fade_start(LEDC_MODE, LEDC_CHANNEL, LEDC_FADE_NO_WAIT);if (ret != ESP_OK) {ESP_LOGE(TAG, "启动淡入淡出失败: %s", esp_err_to_name(ret));return ret;}ESP_LOGI(TAG, "平滑调节亮度至: %d%% (耗时: %ldms)", target_percent, fade_time_ms);return ESP_OK;
}/*** @brief 演示任务 - 展示不同的亮度控制效果*/
void lcd_brightness_demo_task(void *pvParameters)
{ESP_LOGI(TAG, "开始亮度演示...");// 安装淡入淡出服务(用于平滑调节)ledc_fade_func_install(0);// 演示1: 直接设置不同亮度ESP_LOGI(TAG, "=== 演示1: 直接设置亮度 ===");const uint8_t brightness_levels[] = {0, 25, 50, 75, 100};for (int i = 0; i < 5; i++) {lcd_backlight_set_brightness(brightness_levels[i]);vTaskDelay(pdMS_TO_TICKS(1500));}vTaskDelay(pdMS_TO_TICKS(1000));// 演示2: 平滑淡入淡出效果ESP_LOGI(TAG, "=== 演示2: 平滑淡入淡出 ===");lcd_backlight_fade_to(0, 2000); // 淡出到0%,耗时2秒vTaskDelay(pdMS_TO_TICKS(2500));lcd_backlight_fade_to(100, 2000); // 淡入到100%,耗时2秒vTaskDelay(pdMS_TO_TICKS(2500));// 演示3: 呼吸灯效果ESP_LOGI(TAG, "=== 演示3: 呼吸灯效果 ===");for (int cycle = 0; cycle < 3; cycle++) {lcd_backlight_fade_to(10, 1500); // 淡出vTaskDelay(pdMS_TO_TICKS(1500));lcd_backlight_fade_to(100, 1500); // 淡入vTaskDelay(pdMS_TO_TICKS(1500));}// 设置到舒适亮度ESP_LOGI(TAG, "演示结束,设置为70%%亮度");lcd_backlight_set_brightness(70);// 任务结束vTaskDelete(NULL);
}/*** @brief 应用程序主入口*/
void app_main(void)
{ESP_LOGI(TAG, "ESP32 LCD PWM亮度控制演示");ESP_LOGI(TAG, "使用GPIO: %d", LCD_BACKLIGHT_GPIO);// 初始化PWMesp_err_t ret = lcd_backlight_init();if (ret != ESP_OK) {ESP_LOGE(TAG, "初始化失败!");return;}// 创建演示任务xTaskCreate(lcd_brightness_demo_task, "brightness_demo", 4096, NULL, 5, NULL);
}一个完整的ESP32-IDF PWM控制LCD亮度的案例。主要特点:
核心功能
lcd_backlight_init()- 初始化PWM- 使用10位分辨率(0-1023)
- 5kHz PWM频率
lcd_backlight_set_brightness(uint8_t brightness_percent)- 百分比控制亮度- 参数范围:0-100
- 自动转换为PWM占空比
- 包含错误检查
lcd_backlight_fade_to()- 平滑调节- 带淡入淡出效果
- 可自定义过渡时间
使用方法
// 设置50%亮度
lcd_backlight_set_brightness(50);// 平滑调节到80%,耗时1秒
lcd_backlight_fade_to(80, 1000);
注意事项
- 修改GPIO引脚:将
LCD_BACKLIGHT_GPIO改为你的实际背光引脚 - CMakeLists.txt 需包含必要的组件
- 演示任务展示了三种效果:直接设置、淡入淡出、呼吸灯
需要我帮你添加其他功能吗?比如保存亮度设置到NVS、自动亮度调节等?
