使用过GPIO点亮了RGB,它这个里面的色彩灯效不错。
参考:MCU单片机驱动WS2812,点亮RGB灯带各种效果_ws2812数据手册-CSDN博客
四种方式驱动参考:
CH32幻彩灯控 - WS2812及同等类型灯珠的四种驱动方式 - WCH_CH32 - 博客园
另外deepseek生成的AI呼吸灯效,仅参考
#include <stdint.h>
#include <math.h>
// WS2812时序参数(根据实际MCU频率调整)
#define T0H 30 // 0码高电平时间 (ns)
#define T1H 60 // 1码高电平时间 (ns)
#define T0L 60 // 0码低电平时间 (ns)
#define T1L 30 // 1码低电平时间 (ns)
#define RESET_DELAY 80 // 复位信号时间 (us)
// RGB颜色结构体
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
} RGBColor;
// LED数量
#define NUM_LEDS 1
// 全局LED数据数组
RGBColor leds[NUM_LEDS];
// 硬件相关的GPIO操作(需要根据实际平台实现)
void ws2812_send_bit(uint8_t bit) {
if (bit) {
// 发送'1'码
GPIO_SET(HIGH); // 设置GPIO为高
delay_ns(T1H); // 保持高电平时间
GPIO_SET(LOW); // 设置GPIO为低
delay_ns(T1L); // 保持低电平时间
} else {
// 发送'0'码
GPIO_SET(HIGH); // 设置GPIO为高
delay_ns(T0H); // 保持高电平时间
GPIO_SET(LOW); // 设置GPIO为低
delay_ns(T0L); // 保持低电平时间
}
}
// 发送一个字节数据(GRB顺序)
void ws2812_send_byte(uint8_t byte) {
for (int i = 7; i >= 0; i--) {
ws2812_send_bit((byte >> i) & 1);
}
}
// 发送所有LED数据
void ws2812_send_data(void) {
for (int i = 0; i < NUM_LEDS; i++) {
// WS2812使用GRB顺序
ws2812_send_byte(leds[i].g);
ws2812_send_byte(leds[i].r);
ws2812_send_byte(leds[i].b);
}
// 发送复位信号
GPIO_SET(LOW);
delay_us(RESET_DELAY);
}
// 设置LED颜色
void set_led_color(uint8_t index, uint8_t r, uint8_t g, uint8_t b) {
if (index < NUM_LEDS) {
leds[index].r = r;
leds[index].g = g;
leds[index].b = b;
}
}
// 呼吸灯效果
void breathing_effect(uint8_t r, uint8_t g, uint8_t b, uint16_t cycle_time_ms) {
static uint16_t counter = 0;
static uint8_t direction = 0; // 0:渐亮, 1:渐暗
// 计算当前亮度 (使用正弦波实现平滑变化)
float radian = (2 * 3.1415926 * counter) / cycle_time_ms;
float brightness = (sinf(radian - 3.1415926/2) + 1.0) / 2.0; // 0.0 ~ 1.0
// 应用亮度到颜色
uint8_t current_r = (uint8_t)(r * brightness);
uint8_t current_g = (uint8_t)(g * brightness);
uint8_t current_b = (uint8_t)(b * brightness);
// 设置LED颜色
set_led_color(0, current_r, current_g, current_b);
ws2812_send_data();
// 更新计数器
counter++;
if (counter >= cycle_time_ms) {
counter = 0;
}
}
// 简单的线性呼吸灯效果(替代方案)
void simple_breathing_effect(uint8_t r, uint8_t g, uint8_t b, uint16_t speed) {
static uint16_t brightness = 0;
static int8_t direction = 1;
// 更新亮度
brightness += direction * speed;
// 检查边界
if (brightness >= 255) {
brightness = 255;
direction = -1;
} else if (brightness <= 0) {
brightness = 0;
direction = 1;
}
// 计算当前颜色(使用Gamma校正获得更自然的亮度变化)
uint8_t current_r = (uint8_t)((r * brightness) / 255);
uint8_t current_g = (uint8_t)((g * brightness) / 255);
uint8_t current_b = (uint8_t)((b * brightness) / 255);
set_led_color(0, current_r, current_g, current_b);
ws2812_send_data();
}
// 主循环
int main(void) {
// 初始化GPIO和系统时钟
gpio_init();
system_clock_init();
while(1) {
// 红色呼吸灯,周期2000ms
breathing_effect(255, 0, 0, 2000);
delay_ms(10); // 控制刷新率
// 或者使用简单的呼吸灯效果
// simple_breathing_effect(0, 255, 0, 1); // 绿色呼吸灯
}
return 0;
}
// 需要实现的硬件相关函数
void delay_ns(uint32_t ns) {
// 根据MCU频率实现纳秒级延时
// 这通常需要使用精确的循环计数或硬件定时器
}
void delay_us(uint32_t us) {
// 微秒级延时
}
void delay_ms(uint32_t ms) {
// 毫秒级延时
}
void GPIO_SET(uint8_t state) {
// 设置GPIO输出状态
}