以下是基于STM32控制普通RGB灯(共阴极)实现颜色变化的代码示例,通过PWM调光实现渐变、呼吸、彩虹循环等效果。代码使用STM32 HAL库,适配STM32F103系列,其他型号可参考修改定时器和引脚配置。
一、硬件与配置说明
硬件:共阴极RGB灯(R、G、B引脚分别接STM32的TIM2_CH1~CH3);
定时器:TIM2生成3路PWM(频率1kHz,占空比0~100%);
效果:实现彩虹循环、呼吸灯、单色渐变三种常用颜色变化效果。
二、完整代码
1. 头文件与宏定义(rgb_led.h)
#ifndef __RGB_LED_H
#define __RGB_LED_H
#include "stm32f1xx_hal.h"
// 定时器与通道定义(根据实际配置修改)
#define RGB_TIM_HANDLE &htim2
#define R_CHANNEL TIM_CHANNEL_1
#define G_CHANNEL TIM_CHANNEL_2
#define B_CHANNEL TIM_CHANNEL_3
// 亮度范围(0~255)
#define RGB_MAX_BRIGHTNESS 255
// PWM占空比最大值(对应定时器ARR值,需与CubeMX配置一致)
#define PWM_MAX_VALUE 999
// 函数声明
void rgb_init(void);
void rgb_set_color(uint8_t r, uint8_t g, uint8_t b);
void rgb_rainbow_cycle(uint16_t delay_ms);
void rgb_breath_effect(uint8_t r, uint8_t g, uint8_t b, uint16_t period_ms);
void rgb_fade_effect(uint8_t start_r, uint8_t start_g, uint8_t start_b,
uint8_t end_r, uint8_t end_g, uint8_t end_b, uint16_t duration_ms);
#endif
2. 源文件(rgb_led.c)
#include "rgb_led.h"
// 初始化RGB灯(启动PWM)
void rgb_init(void) {
// 启动3路PWM输出(需确保定时器已初始化)
HAL_TIM_PWM_Start(RGB_TIM_HANDLE, R_CHANNEL);
HAL_TIM_PWM_Start(RGB_TIM_HANDLE, G_CHANNEL);
HAL_TIM_PWM_Start(RGB_TIM_HANDLE, B_CHANNEL);
// 初始化为黑色(全灭)
rgb_set_color(0, 0, 0);
}
// 设置RGB颜色(r, g, b范围:0~255)
void rgb_set_color(uint8_t r, uint8_t g, uint8_t b) {
// 将亮度值映射到PWM占空比(0~PWM_MAX_VALUE)
uint32_t pwm_r = (r * PWM_MAX_VALUE) / RGB_MAX_BRIGHTNESS;
uint32_t pwm_g = (g * PWM_MAX_VALUE) / RGB_MAX_BRIGHTNESS;
uint32_t pwm_b = (b * PWM_MAX_VALUE) / RGB_MAX_BRIGHTNESS;
// 设置PWM比较值(占空比)
__HAL_TIM_SET_COMPARE(RGB_TIM_HANDLE, R_CHANNEL, pwm_r);
__HAL_TIM_SET_COMPARE(RGB_TIM_HANDLE, G_CHANNEL, pwm_g);
__HAL_TIM_SET_COMPARE(RGB_TIM_HANDLE, B_CHANNEL, pwm_b);
}
// 彩虹循环效果(依次显示红→橙→黄→绿→青→蓝→紫→红)
void rgb_rainbow_cycle(uint16_t delay_ms) {
// 彩虹色序列(R, G, B)
uint8_t rainbow_colors[][3] = {
{255, 0, 0}, // 红
{255, 165, 0}, // 橙
{255, 255, 0}, // 黄
{0, 255, 0}, // 绿
{0, 255, 255}, // 青
{0, 0, 255}, // 蓝
{128, 0, 128}, // 紫
{255, 0, 0} // 回到红
};
uint8_t color_count = sizeof(rainbow_colors) / sizeof(rainbow_colors[0]);
// 逐个颜色切换
for (uint8_t i = 0; i < color_count; i++) {
rgb_set_color(rainbow_colors[i][0], rainbow_colors[i][1], rainbow_colors[i][2]);
HAL_Delay(delay_ms);
}
}
// 呼吸灯效果(指定颜色的亮度渐变)
void rgb_breath_effect(uint8_t r, uint8_t g, uint8_t b, uint16_t period_ms) {
uint16_t step_delay = period_ms / (2 * RGB_MAX_BRIGHTNESS); // 每个亮度台阶的延时
uint8_t brightness;
// 亮度从0渐增到最大
for (brightness = 0; brightness <= RGB_MAX_BRIGHTNESS; brightness++) {
rgb_set_color(
(r * brightness) / RGB_MAX_BRIGHTNESS,
(g * brightness) / RGB_MAX_BRIGHTNESS,
(b * brightness) / RGB_MAX_BRIGHTNESS
);
HAL_Delay(step_delay);
}
// 亮度从最大渐减到0
for (brightness = RGB_MAX_BRIGHTNESS; brightness > 0; brightness--) {
rgb_set_color(
(r * brightness) / RGB_MAX_BRIGHTNESS,
(g * brightness) / RGB_MAX_BRIGHTNESS,
(b * brightness) / RGB_MAX_BRIGHTNESS
);
HAL_Delay(step_delay);
}
}
// 颜色渐变效果(从起始色平滑过渡到目标色)
void rgb_fade_effect(uint8_t start_r, uint8_t start_g, uint8_t start_b,
uint8_t end_r, uint8_t end_g, uint8_t end_b, uint16_t duration_ms) {
uint16_t steps = 100; // 渐变步数(越多越平滑)
uint16_t step_delay = duration_ms / steps; // 每步延时
int16_t dr = (end_r - start_r) / (int16_t)steps; // R通道每步变化量
int16_t dg = (end_g - start_g) / (int16_t)steps; // G通道每步变化量
int16_t db = (end_b - start_b) / (int16_t)steps; // B通道每步变化量
uint8_t current_r = start_r;
uint8_t current_g = start_g;
uint8_t current_b = start_b;
// 逐步更新颜色
for (uint16_t i = 0; i < steps; i++) {
current_r += dr;
current_g += dg;
current_b += db;
// 确保亮度在0~255范围内
current_r = (current_r < 0) ? 0 : (current_r > 255 ? 255 : current_r);
current_g = (current_g < 0) ? 0 : (current_g > 255 ? 255 : current_g);
current_b = (current_b < 0) ? 0 : (current_b > 255 ? 255 : current_b);
rgb_set_color(current_r, current_g, current_b);
HAL_Delay(step_delay);
}
// 最终颜色确保与目标一致
rgb_set_color(end_r, end_g, end_b);
}
3. 主函数调用(main.c)
#include "stm32f1xx_hal.h"
#include "rgb_led.h"
TIM_HandleTypeDef htim2; // 定时器句柄(需与CubeMX配置一致)
// 定时器初始化函数(由CubeMX自动生成,此处简化)
void MX_TIM2_Init(void) {
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 71; // 72MHz / (71+1) = 1MHz
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 999; // 1MHz / (999+1) = 1kHz PWM
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK) {
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) {
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) {
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) {
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0; // 初始占空比0
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
// 配置3个通道
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) {Error_Handler();}
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) {Error_Handler();}
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) {Error_Handler();}
HAL_TIM_MspPostInit(&htim2); // 初始化GPIO(由CubeMX生成)
}
int main(void) {
HAL_Init();
MX_TIM2_Init(); // 初始化定时器
rgb_init(); // 初始化RGB灯
while (1) {
// 效果1:彩虹循环(每个颜色停留500ms)
rgb_rainbow_cycle(500);
// 效果2:红色呼吸灯(周期2秒)
rgb_breath_effect(255, 0, 0, 2000);
// 效果3:从蓝色渐变到粉色(持续3秒)
rgb_fade_effect(0, 0, 255, 255, 105, 180, 3000);
// 效果4:从绿色渐变到黄色(持续2秒)
rgb_fade_effect(0, 255, 0, 255, 255, 0, 2000);
}
}
// 错误处理函数(简化)
void Error_Handler(void) {
while (1) {}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line) {}
#endif
三、代码说明与使用要点
1. 配置前提
需通过STM32CubeMX配置TIM2的3个通道为PWM输出,参数如下:
预分频器(Prescaler)=71,自动重载值(Counter Period)=999(确保PWM频率1kHz);
通道模式为“PWM Mode 1”,极性为“High”(共阴极适用)。
引脚映射:TIM2_CH1→PA0(R)、TIM2_CH2→PA1(G)、TIM2_CH3→PA2(B)(可根据硬件修改)。
2. 核心函数解析
rgb_set_color():基础函数,通过PWM占空比控制R、G、B亮度;
rgb_rainbow_cycle():循环显示彩虹色,适合氛围灯;
rgb_breath_effect():指定颜色的亮度周期性渐变,模拟呼吸效果;
rgb_fade_effect():从起始色平滑过渡到目标色,适合色彩过渡场景。
3. 适配共阳极RGB灯
若使用共阳极灯,需修改rgb_set_color()中的占空比计算方式(反转逻辑):
// 共阳极:亮度越高,PWM占空比越低(低电平时间越长)
uint32_t pwm_r = PWM_MAX_VALUE - (r * PWM_MAX_VALUE) / RGB_MAX_BRIGHTNESS;
uint32_t pwm_g = PWM_MAX_VALUE - (g * PWM_MAX_VALUE) / RGB_MAX_BRIGHTNESS;
uint32_t pwm_b = PWM_MAX_VALUE - (b * PWM_MAX_VALUE) / RGB_MAX_BRIGHTNESS;
4. 优化建议
若需更平滑的渐变,可增加rgb_fade_effect()中的steps值(如200);
避免在中断中调用颜色控制函数,防止PWM时序紊乱;
多个效果切换时,可通过状态机实现,避免HAL_Delay()阻塞主程序。
通过以上代码,可实现丰富的RGB颜色变化效果,适用于指示灯、氛围灯、交互反馈等场景。
————————————————
版权声明:本文为CSDN博主「Shylock_Mister」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Shylock_Mister/article/details/153576353
|
|