ESP32 RGB组件设计搭建记录
开发软件版本
esp-idf v5.3.1
硬件信息
ESP32
LED低电平有效,R-led IO17 G-led IO4 B-led 16
原理介绍
通过 PWM(脉冲宽度调制)调节红(R)、绿(G)、蓝(B)三色 LED 的亮度占空比,按比例混合出不同颜色(RGB 三原色混合定律)
总体方案设计
LED工作模式
LED总体分为如下工作模式:常亮;常灭;闪烁;呼吸渐强;呼吸渐弱
| 模式枚举值 | 模式名称 | 核心行为定义 | 关键参数 |
|---|---|---|---|
LED_MODE_ON | 常亮 | 固定目标亮度持续输出,PWM 占空比恒定,无渐变 / 闪烁,定时器持续运行 | 目标 RGB 亮度(0-255) |
LED_MODE_OFF | 常灭 | PWM 占空比强制设 0,暂停 LEDC 定时器(低功耗),所有参数不生效 | 无(仅启停控制) |
LED_MODE_BLINK | 闪烁 | 固定目标亮度 “亮 - 灭” 切换,亮 / 灭时长由 “总周期 + 占空比” 决定,无渐变 | 总周期(≥10ms)、亮灯占空比(0-100%)、目标 RGB 亮度 |
LED_MODE_BREATH_UP | 呼吸渐强 | 从 0 亮度线性渐变到目标最大亮度,渐变完成后停在最大亮度(可选循环) | 渐变总时长(ms)、目标 RGB 亮度、最大亮度(0-255) |
LED_MODE_BREATH_DOWN | 呼吸渐弱 | 从目标最大亮度线性渐变到 0 亮度,渐变完成后停在 0 亮度(可选循环) | 渐变总时长(ms)、目标 RGB 亮度、最大亮度(0-255) |
宏定义
/************************* 硬件&LEDC配置宏 *************************/
#define LED_R_IO GPIO_NUM_17
#define LED_G_IO GPIO_NUM_4
#define LED_B_IO GPIO_NUM_16
#define LEDC_TIMER LEDC_TIMER_0
#define LEDC_MODE LEDC_LOW_SPEED_MODE
#define LEDC_CHANNEL_R LEDC_CHANNEL_0
#define LEDC_CHANNEL_G LEDC_CHANNEL_1
#define LEDC_CHANNEL_B LEDC_CHANNEL_2
#define LEDC_DUTY_RES LEDC_TIMER_10_BIT // 10位分辨率(0-1023)
#define LEDC_FREQ_HZ 5000 // 5kHz无频闪
#define BRIGHTNESS_TO_DUTY(bright) ((uint32_t)(bright) * 1023 / 255)
数据结构设计
/************************* 模式&状态定义 *************************/
// LED工作模式
typedef enum _led_work_mode {
LED_MODE_OFF = 0, // 常灭
LED_MODE_ON, // 常亮
LED_MODE_BLINK, // 闪烁
LED_MODE_BREATH_UP, // 呼吸渐强(0→最大亮度)
LED_MODE_BREATH_DOWN, // 呼吸渐弱(最大→0亮度)
LED_MODE_MAX // 模式边界
} led_work_mode;
// 闪烁/呼吸状态(用于定时器回调状态机)
typedef enum _led_run_state {
LED_STATE_IDLE, // 空闲
LED_STATE_BLINK_ON, // 闪烁-亮
LED_STATE_BLINK_OFF, // 闪烁-灭
LED_STATE_BREATH_UP, // 呼吸-渐强中
LED_STATE_BREATH_DOWN // 呼吸-渐弱中
} led_run_state;
/************************* 全局配置结构体 *************************/
typedef struct _rgb_color_conf {
uint8_t red; // 0-255
uint8_t green; // 0-255
uint8_t blue; // 0-255
} rgb_color_conf;
typedef struct _rgb_led_global_conf {
// 基础配置
rgb_color_conf color; // 当前颜色
led_work_mode work_mode; // 工作模式
led_run_state run_state; // 运行状态
bool led_turn_on; // 总启用开关
// 模式参数
uint16_t total_period_ms; // 基础周期(闪烁/呼吸通用,ms)
uint8_t turn_on_per; // 闪烁占空比(0-100%)
uint8_t breath_max_bright; // 呼吸最大亮度(0-255)
// 定时器句柄
TimerHandle_t led_timer; // 软件定时器句柄
} rgb_led_global_conf;
// 预设颜色枚举&数组
typedef enum _G_COLOR {
G_COLOR_RED_STANDARD, // 0
G_COLOR_ORANGE_STANDARD, // 1
G_COLOR_YELLOW_STANDARD, // 2
G_COLOR_GREEN_STANDARD, // 3
G_COLOR_CYAN_STANDARD, // 4
G_COLOR_BLUE_STANDARD, // 5
G_COLOR_PURPLE_STANDARD, // 6
G_COLOR_MAX // 7
} G_COLOR;
static const rgb_color_conf g_rgb_color_list[] = {
{255, 0, 0}, // 红
{255, 165, 0}, // 橙
{255, 255, 0}, // 黄
{0, 255, 0}, // 绿
{0, 255, 255}, // 青
{0, 0, 255}, // 蓝
{255, 0, 255} // 紫
};
// 全局配置初始化
static rgb_led_global_conf g_rgb_led_conf = {
.color = {0, 0, 0},
.work_mode = LED_MODE_OFF,
.run_state = LED_STATE_IDLE,
.led_turn_on = false,
.total_period_ms = 2000,
.turn_on_per = 50,
.breath_max_bright = 255,
.led_timer = NULL
};
接口说明
私有接口
/************************* 私有函数实现 *************************/
/** * @brief LEDC定时器启停 */
static void ledc_timer_control(bool enable)
/** * @brief PWM初始化 */
static void rgb_led_pwm_init(void)
/** * @brief 设置PWM占空比 */
static void rgb_led_set_pwm(rgb_color_conf *color)
/** * @brief 清空PWM(灭灯) */
static void rgb_led_clear_pwm(void)
/** * @brief 呼吸渐变控制 */
static void rgb_led_breath_fade(led_work_mode fade_mode)
/** * @brief 软件定时器回调函数 */
static void led_timer_callback(TimerHandle_t xTimer)
对外接口
/**
* @brief 切换LED工作模式
* @param mode 目标模式
* @return 0:成功, -1:参数非法
*/
int set_rgb_led_mode(led_work_mode mode)
/**
* @brief 设置自定义颜色
* @param r/g/b 亮度(0-255)
* @return 0:成功
*/
int set_rgb_led_custom_color(uint8_t r, uint8_t g, uint8_t b)
/**
* @brief 设置预设颜色
* @param color 预设枚举
* @return 0:成功, -1:参数非法
*/
int set_rgb_led_color(G_COLOR color)
/**
* @brief 设置闪烁参数
* @param period_ms 总周期(≥10ms)
* @param on_per 占空比(0-100%
* @return 0:成功, -1:参数非法
*/
int set_rgb_led_blink_param(uint16_t period_ms, uint8_t on_per)
/**
* @brief 设置呼吸灯参数 * @param period_ms 渐变时长(≥500ms)
* @param max_bright 最大亮度(0-255)
* @return 0:成功, -1:参数非法
*/
int set_rgb_led_breath_param(uint16_t period_ms, uint8_t max_bright)
/**
* @brief 总启停控制(联动低功耗)
* @param enable true:启用 false:禁用
* @return 操作后状态 */
bool turn_on_off_led(bool enable)
/**
* @brief 获取当前模式
* @return 当前工作模式
*/
led_work_mode get_rgb_led_mode(void)
接口实现
#include <stdio.h>
/************************* 私有函数 *************************/
/**
* @brief LEDC定时器启停
*/
static void ledc_timer_control(bool enable)
{
if (enable)
{
ledc_timer_resume(LEDC_MODE, LEDC_TIMER);
}
else
{
ledc_timer_pause(LEDC_MODE, LEDC_TIMER);
}
}
/**
* @brief PWM初始化
*/
static void rgb_led_pwm_init(void)
{
// LEDC定时器配置
ledc_timer_config_t ledc_timer =
{
.duty_resolution = LEDC_DUTY_RES,
.freq_hz = LEDC_FREQ_HZ,
.speed_mode = LEDC_MODE,
.timer_num = LEDC_TIMER,
.clk_cfg = LEDC_AUTO_CLK
};
ledc_timer_config(&ledc_timer);
// 通道配置:初始duty=LED_DUTY_OFF(灭灯)
ledc_channel_config_t ch_r =
{
.channel=LEDC_CHANNEL_R,
.duty=LED_DUTY_OFF, // 宏控:灭灯占空比
.gpio_num=LED_R_IO,
.speed_mode=LEDC_MODE,
.timer_sel=LEDC_TIMER
};
ledc_channel_config_t ch_g =
{
.channel=LEDC_CHANNEL_G,
.duty=LED_DUTY_OFF, // 宏控:灭灯占空比
.gpio_num=LED_G_IO,
.speed_mode=LEDC_MODE,
.timer_sel=LEDC_TIMER
};
ledc_channel_config_t ch_b =
{
.channel=LEDC_CHANNEL_B,
.duty=LED_DUTY_OFF, // 宏控:灭灯占空比
.gpio_num=LED_B_IO,
.speed_mode=LEDC_MODE,
.timer_sel=LEDC_TIMER
};
ledc_channel_config(&ch_r);
ledc_channel_config(&ch_g);
ledc_channel_config(&ch_b);
// 启用渐变功能
ledc_fade_func_install(0);
}
/**
* @brief 设置PWM占空比
*/
static void rgb_led_set_pwm(rgb_color_conf *color)
{
if (!color)
{
return;
}
uint32_t r_duty = BRIGHTNESS_TO_DUTY(color->red * g_rgb_led_conf.breath_max_bright / 255);
uint32_t g_duty = BRIGHTNESS_TO_DUTY(color->green * g_rgb_led_conf.breath_max_bright / 255);
uint32_t b_duty = BRIGHTNESS_TO_DUTY(color->blue * g_rgb_led_conf.breath_max_bright / 255);
ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_R, r_duty);
ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_G, g_duty);
ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_B, b_duty);
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_R);
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_G);
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_B);
}
/**
* @brief 清空PWM(灭灯)
*/
static void rgb_led_clear_pwm(void)
{
ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_R, LED_DUTY_OFF);
ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_G, LED_DUTY_OFF);
ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_B, LED_DUTY_OFF);
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_R);
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_G);
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_B);
}
/**
* @brief 呼吸渐变控制
*/
static void rgb_led_breath_fade(led_work_mode fade_mode)
{
rgb_color_conf fade_color = g_rgb_led_conf.color;
fade_color.red = fade_color.red * g_rgb_led_conf.breath_max_bright / 255;
fade_color.green = fade_color.green * g_rgb_led_conf.breath_max_bright / 255;
fade_color.blue = fade_color.blue * g_rgb_led_conf.breath_max_bright / 255;
if (fade_mode == LED_MODE_BREATH_UP)
{
// 渐强:0→最大亮度 → 宏控占空比映射
uint32_t r_duty = BRIGHTNESS_TO_DUTY(fade_color.red);
uint32_t g_duty = BRIGHTNESS_TO_DUTY(fade_color.green);
uint32_t b_duty = BRIGHTNESS_TO_DUTY(fade_color.blue);
ledc_set_fade_time_and_start(LEDC_MODE, LEDC_CHANNEL_R, r_duty, g_rgb_led_conf.total_period_ms, LEDC_FADE_NO_WAIT);
ledc_set_fade_time_and_start(LEDC_MODE, LEDC_CHANNEL_G, g_duty, g_rgb_led_conf.total_period_ms, LEDC_FADE_NO_WAIT);
ledc_set_fade_time_and_start(LEDC_MODE, LEDC_CHANNEL_B, b_duty, g_rgb_led_conf.total_period_ms, LEDC_FADE_NO_WAIT);
}
else
{
// 渐弱:最大亮度→0 → 宏控灭灯占空比
ledc_set_fade_time_and_start(LEDC_MODE, LEDC_CHANNEL_R, LED_DUTY_OFF, g_rgb_led_conf.total_period_ms, LEDC_FADE_NO_WAIT);
ledc_set_fade_time_and_start(LEDC_MODE, LEDC_CHANNEL_G, LED_DUTY_OFF, g_rgb_led_conf.total_period_ms, LEDC_FADE_NO_WAIT);
ledc_set_fade_time_and_start(LEDC_MODE, LEDC_CHANNEL_B, LED_DUTY_OFF, g_rgb_led_conf.total_period_ms, LEDC_FADE_NO_WAIT);
}
}
/**
* 定时器回调
*/
static void led_timer_callback(TimerHandle_t xTimer)
{
if (!g_rgb_led_conf.led_turn_on)
{
return;
}
switch (g_rgb_led_conf.work_mode)
{
case LED_MODE_ON:
rgb_led_set_pwm(&g_rgb_led_conf.color);
break;
case LED_MODE_BLINK:
if (g_rgb_led_conf.run_state == LED_STATE_BLINK_ON)
{
rgb_led_set_pwm(&g_rgb_led_conf.color);
g_rgb_led_conf.run_state = LED_STATE_BLINK_OFF;
xTimerChangePeriod(xTimer,
pdMS_TO_TICKS(g_rgb_led_conf.total_period_ms - (g_rgb_led_conf.total_period_ms * g_rgb_led_conf.turn_on_per / 100)), 0);
}
else
{
rgb_led_clear_pwm();
g_rgb_led_conf.run_state = LED_STATE_BLINK_ON;
xTimerChangePeriod(xTimer,
pdMS_TO_TICKS(g_rgb_led_conf.total_period_ms * g_rgb_led_conf.turn_on_per / 100), 0);
}
break;
case LED_MODE_BREATH_UP:
rgb_led_breath_fade(LED_MODE_BREATH_UP);
break;
case LED_MODE_BREATH_DOWN:
rgb_led_breath_fade(LED_MODE_BREATH_DOWN);
break;
default:
rgb_led_clear_pwm();
break;
}
}
/************************* 对外接口 *************************/
/**
* @brief 切换LED工作模式
* @param mode 目标模式
* @return 0:成功, -1:参数非法
*/
int set_rgb_led_mode(led_work_mode mode)
{
if (mode >= LED_MODE_MAX || !g_rgb_led_conf.led_timer)
{
return -1;
}
g_rgb_led_conf.work_mode = mode;
g_rgb_led_conf.run_state = LED_STATE_IDLE;
switch (mode)
{
case LED_MODE_ON:
xTimerChangePeriod(g_rgb_led_conf.led_timer, pdMS_TO_TICKS(100), 0);
break;
case LED_MODE_OFF:
xTimerStop(g_rgb_led_conf.led_timer, 0);
rgb_led_clear_pwm();
ledc_timer_control(false);
return 0;
case LED_MODE_BLINK:
g_rgb_led_conf.run_state = LED_STATE_BLINK_ON;
xTimerChangePeriod(g_rgb_led_conf.led_timer,
pdMS_TO_TICKS(g_rgb_led_conf.total_period_ms * g_rgb_led_conf.turn_on_per / 100), 0);
break;
case LED_MODE_BREATH_UP:
case LED_MODE_BREATH_DOWN:
g_rgb_led_conf.run_state =
(mode == LED_MODE_BREATH_UP) ? LED_STATE_BREATH_UP : LED_STATE_BREATH_DOWN;
xTimerChangePeriod(g_rgb_led_conf.led_timer, pdMS_TO_TICKS(g_rgb_led_conf.total_period_ms), 0);
break;
default:
break;
}
if (g_rgb_led_conf.led_turn_on)
{
ledc_timer_control(true);
xTimerStart(g_rgb_led_conf.led_timer, 0);
}
return 0;
}
/**
* @brief 设置自定义颜色
* @param r/g/b 亮度(0-255)
* @return 0:成功
*/
int set_rgb_led_custom_color(uint8_t r, uint8_t g, uint8_t b)
{
g_rgb_led_conf.color.red = r > 255 ? 255 : r;
g_rgb_led_conf.color.green = g > 255 ? 255 : g;
g_rgb_led_conf.color.blue = b > 255 ? 255 : b;
if (g_rgb_led_conf.led_turn_on && g_rgb_led_conf.work_mode == LED_MODE_ON)
{
rgb_led_set_pwm(&g_rgb_led_conf.color);
}
return 0;
}
/**
* @brief 设置预设颜色
* @param color 预设枚举
* @return 0:成功, -1:参数非法
*/
int set_rgb_led_color(G_COLOR color)
{
if (color >= G_COLOR_MAX)
{
return -1;
}
g_rgb_led_conf.color = g_rgb_color_list[color];
if (g_rgb_led_conf.led_turn_on && g_rgb_led_conf.work_mode == LED_MODE_ON)
{
rgb_led_set_pwm(&g_rgb_led_conf.color);
}
return 0;
}
/**
* @brief 设置闪烁参数
* @param period_ms 总周期(≥10ms)
* @param on_per 占空比(0-100%
* @return 0:成功, -1:参数非法
*/
int set_rgb_led_blink_param(uint16_t period_ms, uint8_t on_per)
{
if (period_ms < 10 || on_per > 100)
{
return -1;
}
g_rgb_led_conf.total_period_ms = period_ms;
g_rgb_led_conf.turn_on_per = on_per;
if (g_rgb_led_conf.work_mode == LED_MODE_BLINK && g_rgb_led_conf.led_turn_on)
{
set_rgb_led_mode(LED_MODE_BLINK);
}
return 0;
}
/**
* @brief 设置呼吸灯参数 * @param period_ms 渐变时长(≥500ms)
* @param max_bright 最大亮度(0-255)
* @return 0:成功, -1:参数非法
*/
int set_rgb_led_breath_param(uint16_t period_ms, uint8_t max_bright)
{
if (period_ms < 500 || max_bright > 255)
{
return -1;
}
g_rgb_led_conf.total_period_ms = period_ms;
g_rgb_led_conf.breath_max_bright = max_bright;
if ((g_rgb_led_conf.work_mode == LED_MODE_BREATH_UP
|| g_rgb_led_conf.work_mode == LED_MODE_BREATH_DOWN)
&& g_rgb_led_conf.led_turn_on)
{
set_rgb_led_mode(g_rgb_led_conf.work_mode);
}
return 0;
}
/**
* @brief 总启停控制
* @param enable true:启用 false:禁用
* @return 操作后状态 */
bool turn_on_off_led(bool enable)
{
g_rgb_led_conf.led_turn_on = enable;
if (enable)
{
ledc_timer_control(true);
set_rgb_led_mode(g_rgb_led_conf.work_mode);
}
else
{
xTimerStop(g_rgb_led_conf.led_timer, 0);
rgb_led_clear_pwm();
ledc_timer_control(false);
}
return enable;
}
/**
* @brief 获取当前模式
* @return 当前工作模式
*/
led_work_mode get_rgb_led_mode(void)
{
return g_rgb_led_conf.work_mode;
}
/************************* 初始化 *************************/
void rgb_led_init(void)
{
rgb_led_pwm_init();
g_rgb_led_conf.led_timer = xTimerCreate(
"led_timer",
pdMS_TO_TICKS(100),
pdTRUE,
NULL,
led_timer_callback
);
if (g_rgb_led_conf.led_timer)
{
xTimerStop(g_rgb_led_conf.led_timer, 0);
}
ledc_timer_control(false);
}
Demo进程
#include <stdio.h>
#include "RGBLED.h"
void app_main(void)
{
rgb_led_init();
turn_on_off_led(true);
set_rgb_led_custom_color(0, 0, 255);
set_rgb_led_mode(LED_MODE_BLINK);
set_rgb_led_blink_param(1000, 50);
vTaskDelay(pdMS_TO_TICKS(5000));
set_rgb_led_mode(LED_MODE_OFF);
turn_on_off_led(false);
while (1)
{
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
应用场景
不同颜色的LED代表当前不同阶段,比如wifi连接时/系统启动等
代码获取
https://download.youkuaiyun.com/download/stuinxdu/92479470
774

被折叠的 条评论
为什么被折叠?



