基于STM32的WS2812B炫彩灯光控制系统
这个项目是一个高效稳定的WS2812B RGB LED灯带驱动库,专为STM32F103系列微控制器设计。通过PWM和DMA技术实现精确的时序控制,支持多达60个LED灯珠,提供了丰富的灯光效果和灵活的配置选项。
效果图
(只拍摄了部分效果)
核心功能亮点
-
专业级硬件驱动
- 零等待DMA传输技术
- 自动生成WS2812B协议波形(800kHz)
- 精确的复位信号控制(>50μs低电平)
-
11种炫彩特效
// 彩虹波浪效果 Effect_RainbowWave(8, 3); // 呼吸灯效果 Effect_Breathe(COLOR_BLUE, 50, 5); // 奔跑光带 Effect_RunningLights(COLOR_GREEN, 25, 80, 5); // 音乐频谱效果 Effect_SingleMusicBar(COLOR_RED, 75, 500);
-
卓越的性能优化
- 呼吸灯查表算法替代浮点运算
- HSV转RGB快速转换函数
- 内存占用优化(双缓冲设计)
- 动态延时控制技术
技术架构
关键特性
-
物理层
- 工作电压:灯珠5V,信号线电压3.3V既可。
- 信号频率:800kHz ±150ppm
- 支持灯珠数:60个(可配置)
-
色彩系统
- GRB 24位真色彩
- HSV色彩空间支持
- 预定义常用颜色常量
#define COLOR_RED 0x00FF00 #define COLOR_PURPLE 0x00FF80
-
控制接口
- 速度参数:1-100可调
- 循环次数:0=永久运行
- 亮度控制:0-255级
使用示例
while(1) {
// 彩虹波浪效果
Effect_RainbowWave(8, 3);
// 音乐频谱效果
Effect_SingleMusicBar(COLOR_RED, 75, 500);
// 双向流水灯
Effect_BidirectionalFlow(COLOR_CYAN, 70, 3);
// 清屏暂停
WS2812B_Clear();
Delay_ms(1000);
}
应用场景
- 智能家居氛围照明
- 音乐可视化系统
- 节日装饰灯光
- 汽车氛围灯
- 游戏设备RGB灯效
该项目以卓越的性能和丰富的灯光效果,为嵌入式开发者提供了开箱即用的WS2812B解决方案。所有代码采用模块化设计,方便移植到各种STM32平台,并通过详尽的注释确保可维护性。
下面是全部的代码(粘贴既可使用)
主函数代码(main.c)
#include "stm32f10x.h"
#include "HDL_WS2812B.h"
#include "Delay.h"
int main(void)
{
// 系统时钟初始化 (根据实际配置)
SystemInit();
// WS2812B初始化
PWM_WS2812B_Init(WS2812B_ARR);
WS2812B_Clear();
while (1) {
// 0.显示 x色频谱条,中等速度,运行 次
Effect_SingleMusicBar(COLOR_RED, 75, 500);
// 1. 彩虹波浪效果
Effect_RainbowWave(8, 3); // 中等速度,运行3个循环
// 2. 呼吸灯效果 (蓝色)
Effect_Breathe(COLOR_BLUE, 50, 5); // 蓝色,中等速度,5次呼吸循环
// 3. 颜色循环效果
Effect_ColorCycle(30, 10); // 较慢速度,运行3个循环
// 4. 奔跑光带效果 (绿色)
Effect_RunningLights(COLOR_GREEN, 25, 80, 5); // 绿色,宽度6,慢速,运行5个循环
// 5. 快速闪烁效果 (红色/绿色交替)
Effect_Flash(COLOR_RED, COLOR_GREEN, 70, 10); // 红绿色交替,快速,闪烁10次
// 6. 白色渐变效果
Effect_WhiteFade(200, 60, 3); // 最大亮度200,慢速,3次渐变循环
// 7. 随机闪烁效果
Effect_RandomTwinkle(70, 20); // 中等速度,闪烁20次
// 8. 跳动条效果 (紫色)
Effect_JumpingBar(COLOR_PURPLE, 4, 5, 10, 10); // 紫色,条长4,间隔5,慢速,运行10个循环
// 9. 单向流水灯效果 (青色)
Effect_WaterFlow(COLOR_CYAN, 80, 3); // 青色,慢速,3次流水
//
// 10. 双向流水灯效果 (紫色)
Effect_BidirectionalFlow(COLOR_PURPLE, 70, 3); // 白色,中等速度,运行3个循环
//
// 短暂停顿
WS2812B_Clear();
Delay_ms(1000);
}
}
HDL_WS2812B.c文件
/*******************************************************************************
* @file HDL_WS2812B.c
* @author
* @version V1.0
* @date 2025
* @brief Improved WS2812B driver with multiple effects
******************************************************************************/
#include "HDL_WS2812B.h"
#include "Delay.h"
#include "stdlib.h" // For random effects
/* 单个灯珠的编码对应的比较值数组 */
uint16_t Single_LED_Buffer[DATA_SIZE * LED_NUM];
/* 存储所有灯珠的颜色数据 (GRB格式) */
uint32_t LED_Color[LED_NUM];
// HSV转RGB函数
static uint32_t HSVtoRGB(uint16_t h, uint8_t s, uint8_t v);
/*
* 初始化函数
* 参数:arr:自动重装值
*/
void PWM_WS2812B_Init(uint16_t arr)
{
//结构体变量
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
DMA_InitTypeDef DMA_InitStructure;
//使能RCC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PORTA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //使能TIM2时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); //使能DMA1时钟
//初始化GPIO口
GPIO_InitStructure.GPIO_Pin = WS2812B_PIN; //GPIO口
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(WS2812B_PORT,&GPIO_InitStructure); //根据指定的参数初始化GPIO口
//初始化TIM2
TIM_TimeBaseStructure.TIM_Prescaler=0; //定时器分频:(0+1)=1,不分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //时钟分割
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); //根据指定的参数初始化TIM2
//初始化TIM2 Channel2 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
//TIM_OCInitStructure.TIM_Pulse = 0; //待装入捕获比较寄存器的脉冲值(此程序不用加初值)
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC2Init(TIM2, &TIM_OCInitStructure); //根据指定的参数初始化外设TIM2 Channel2
/* 此处为知识点所描述处的对应代码,一定要有。移植时注意0C2代表定时器通道2*/
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR2上的预装载寄存器
TIM_Cmd(TIM2, DISABLE); //失能TIM2,防止第一个脉冲异常
TIM_DMACmd(TIM2, TIM_DMA_CC2, ENABLE); //使能TIM2_CH2的DMA功能(CC2对应通道2)
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TIM2->CCR2); //设置DMA目的地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Single_LED_Buffer; //设置DMA源地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //方向:从内存SendBuff到内存ReceiveBuff
DMA_InitStructure.DMA_BufferSize = DATA_SIZE; //一次传输大小DMA_BufferSize=SendBuffSize 先这样,后面可以通过库函数修改
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //ReceiveBuff地址不增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //SendBuff地址自增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //ReceiveBuff数据单位,16bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //SENDBUFF_SIZE数据单位,16bit
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //DMA模式:正常模式(传输一次)
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //优先级:中
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //内存到内存的传输
DMA_Init(DMA1_Channel7, &DMA_InitStructure); //配置DMA1的7通道(不同定时器的通道不一样)
DMA_Cmd(DMA1_Channel7, DISABLE); //失能DMA1的7通道,因为一旦使能就开始传输
}
/**
* @brief 发送复位信号(>50us低电平)
*/
void WS2812B_Reset(void)
{
TIM_Cmd(TIM2, DISABLE); // 关闭定时器
WS2812B_LOW; // 输出低电平
Delay_us(60); // 精确延时60us
}
/**
* @brief 将颜色数据编码为PWM波形数据
*/
void WS2812B_Encode(void)
{
for (int i = 0; i < LED_NUM; i++) {
uint32_t grb = LED_Color[i];
for (int j = 0; j < 24; j++) {
// 从高位开始编码
if (grb & (0x800000 >> j)) {
Single_LED_Buffer[i * 24 + j] = T1H;
} else {
Single_LED_Buffer[i * 24 + j] = T0H;
}
}
}
}
/**
* @brief 显示已编码的数据
*/
void WS2812B_Show(void)
{
WS2812B_Encode();
WS2812B_Reset();
DMA_SetCurrDataCounter(DMA1_Channel7, LED_NUM * DATA_SIZE);
DMA_Cmd(DMA1_Channel7, ENABLE);
TIM_Cmd(TIM2, ENABLE);
while (DMA_GetFlagStatus(DMA1_FLAG_TC7) == RESET); // 等待DMA完成
DMA_Cmd(DMA1_Channel7, DISABLE);
DMA_ClearFlag(DMA1_FLAG_TC7);
TIM_Cmd(TIM2, DISABLE);
}
/**
* @brief 设置单个灯珠颜色
* @param index: 灯珠索引 (0~LED_NUM-1)
* @param color: GRB格式的颜色值
*/
void WS2812B_SetPixel(uint16_t index, uint32_t color)
{
if (index < LED_NUM) {
LED_Color[index] = color;
}
}
/**
* @brief 设置所有灯珠为相同颜色
* @param color: GRB格式的颜色值
*/
void WS2812B_SetAll(uint32_t color)
{
for (int i = 0; i < LED_NUM; i++) {
LED_Color[i] = color;
}
}
/**
* @brief 清除所有灯珠(黑色)
*/
void WS2812B_Clear(void)
{
WS2812B_SetAll(0x000000);
WS2812B_Show();
}
/******************************* 显示效果函数 *******************************/
/**
* @brief 彩虹波浪效果
* @param speed: 效果速度 (1-100)
* @param iterations: 迭代次数 (0=永久)
*/
void Effect_RainbowWave(uint8_t speed, uint16_t iterations)
{
uint16_t hue = 0;
uint16_t counter = 0;
do {
for (int i = 0; i < LED_NUM; i++) {
// 计算每个灯珠的HSV值
uint16_t pixel_hue = (hue + i * 360 / LED_NUM) % 360;
WS2812B_SetPixel(i, HSVtoRGB(pixel_hue, 255, 255));
}
WS2812B_Show();
Delay_s(10 - speed);
hue = (hue + 5) % 360;
counter++;
} while (iterations == 0 || counter < iterations);
}
/**
* @brief 改进的呼吸灯效果
* @param color: 基础颜色 (GRB格式)
* @param speed: 效果速度 (1-100)
* @param iterations: 呼吸周期次数 (0=永久)
*/
void Effect_Breathe(uint32_t color, uint8_t speed, uint16_t iterations)
{
uint16_t counter = 0;
uint8_t r_base = (color >> 16) & 0xFF;
uint8_t g_base = (color >> 8) & 0xFF;
uint8_t b_base = color & 0xFF;
// 使用查表法替代三角函数计算,更高效且避免浮点运算
static const uint8_t breathe_table[256] = {
0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 13, 14, 16, 17, 19, 21, 23, 25, 27, 29, 31, 33,
36, 38, 41, 43, 46, 49, 52, 55, 58, 61, 64, 67, 71, 74, 78, 81,
85, 89, 93, 97, 101, 105, 109, 113, 118, 122, 127, 131, 136, 140, 145, 150,
155, 159, 164, 169, 174, 179, 184, 189, 194, 199, 204, 209, 214, 219, 224, 229,
234, 238, 243, 248, 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 253, 252, 252, 251, 250, 249,
248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233,
232, 230, 229, 228, 226, 225, 224, 222, 221, 219, 218, 216, 215, 213, 211, 210,
208, 206, 205, 203, 201, 199, 197, 196, 194, 192, 190, 188, 186, 184, 182, 180,
178, 176, 174, 172, 170, 167, 165, 163, 161, 159, 156, 154, 152, 150, 147, 145,
143, 141, 138, 136, 134, 131, 129, 127, 124, 122, 120, 117, 115, 113, 110, 108,
106, 103, 101, 99, 97, 94, 92, 90, 88, 85, 83, 81, 79, 76, 74, 72
};
do {
// 亮度增加阶段(吸)
for (int i = 0; i < 256; i++) {
uint8_t level = breathe_table[i];
uint8_t r = (r_base * level) >> 8; // 右移8位等效于除以256
uint8_t g = (g_base * level) >> 8;
uint8_t b = (b_base * level) >> 8;
WS2812B_SetAll(((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
WS2812B_Show();
// 动态延时控制
Delay_us(800 + (200 * (255 - level)) / (speed + 10));
}
// 亮度减少阶段(呼)
for (int i = 255; i >= 0; i--) {
uint8_t level = breathe_table[i];
uint8_t r = (r_base * level) >> 8;
uint8_t g = (g_base * level) >> 8;
uint8_t b = (b_base * level) >> 8;
WS2812B_SetAll(((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
WS2812B_Show();
// 动态延时控制
Delay_us(800 + (200 * (255 - level)) / (speed + 10));
}
counter++;
} while (iterations == 0 || counter < iterations);
}
/**
* @brief 颜色循环效果
* @param speed: 效果速度 (1-100)
* @param iterations: 循环次数 (0=永久)
*/
void Effect_ColorCycle(uint8_t speed, uint16_t iterations)
{
uint16_t hue = 0;
uint16_t counter = 0;
do {
uint32_t color = HSVtoRGB(hue, 255, 255);
WS2812B_SetAll(color);
WS2812B_Show();
Delay_ms(100 - speed);
hue = (hue + 30) % 360;
counter++;
} while (iterations == 0 || counter < iterations);
}
/**
* @brief 奔跑光带效果
* @param color: 光带颜色 (GRB格式)
* @param width: 光带宽度
* @param speed: 效果速度 (1-100)
* @param iterations: 循环次数 (0=永久)
*/
void Effect_RunningLights(uint32_t color, uint8_t width, uint8_t speed, uint16_t iterations)
{
int8_t position = 0;
uint16_t counter = 0;
do {
WS2812B_Clear();
// 创建奔跑光带
for (int i = 0; i < width; i++) {
int pos = (position + i) % LED_NUM;
if (pos < 0) pos += LED_NUM;
WS2812B_SetPixel(pos, color);
}
WS2812B_Show();
Delay_ms(100 - speed);
position = (position + 1) % LED_NUM;
counter++;
} while (iterations == 0 || counter < iterations);
}
/**
* @brief 快速闪烁效果
* @param color1: 颜色1 (GRB格式)
* @param color2: 颜色2 (GRB格式)
* @param speed: 闪烁速度 (1-100)
* @param flashes: 闪烁次数 (0=永久)
*/
void Effect_Flash(uint32_t color1, uint32_t color2, uint8_t speed, uint16_t flashes)
{
uint16_t counter = 0;
do {
WS2812B_SetAll(color1);
WS2812B_Show();
Delay_ms(200 - speed);
WS2812B_SetAll(color2);
WS2812B_Show();
Delay_ms(200 - speed);
counter++;
} while (flashes == 0 || counter < flashes);
}
/**
* @brief 白色渐变效果
* @param brightness: 最大亮度 (0-255)
* @param speed: 渐变速度 (1-100)
* @param iterations: 迭代次数 (0=永久)
*/
void Effect_WhiteFade(uint8_t brightness, uint8_t speed, uint16_t iterations)
{
uint16_t counter = 0;
do {
// 渐亮
for (int i = 0; i <= brightness; i++) {
uint32_t color = ((uint32_t)i << 16) | ((uint32_t)i << 8) | i;
WS2812B_SetAll(color);
WS2812B_Show();
Delay_ms(20);
}
// 渐暗
for (int i = brightness; i >= 0; i--) {
uint32_t color = ((uint32_t)i << 16) | ((uint32_t)i << 8) | i;
WS2812B_SetAll(color);
WS2812B_Show();
Delay_ms(20);
}
counter++;
} while (iterations == 0 || counter < iterations);
}
/**
* @brief 随机闪烁效果
* @param speed: 闪烁速度 (1-100)
* @param flashes: 闪烁次数 (0=永久)
*/
void Effect_RandomTwinkle(uint8_t speed, uint16_t flashes)
{
uint16_t counter = 0;
do {
WS2812B_Clear();
// 随机选择几个灯珠
int num_twinkles = 5 + rand() % 5;
for (int i = 0; i < num_twinkles; i++) {
int pos = rand() % LED_NUM;
uint32_t color = HSVtoRGB(rand() % 360, 255, 100 + rand() % 155);
WS2812B_SetPixel(pos, color);
}
WS2812B_Show();
Delay_ms(200 - speed);
counter++;
} while (flashes == 0 || counter < flashes);
}
/**
* @brief 跳动条效果
* @param color: 条形颜色 (GRB格式)
* @param bar_length: 条的长度
* @param gap: 条之间的间隔
* @param speed: 效果速度 (1-100)
* @param iterations: 迭代次数 (0=永久)
*/
void Effect_JumpingBar(uint32_t color, uint8_t bar_length, uint8_t gap, uint8_t speed, uint16_t iterations)
{
int position = 0;
uint16_t counter = 0;
int direction = 1;
do {
WS2812B_Clear();
// 创建跳动条
for (int bar = 0; bar < LED_NUM; bar += (bar_length + gap)) {
int start = (position + bar) % LED_NUM;
for (int i = 0; i < bar_length; i++) {
int pos = (start + i) % LED_NUM;
WS2812B_SetPixel(pos, color);
}
}
WS2812B_Show();
Delay_ms(100 - speed);
// 更新位置和方向
position = (position + direction * 5) % LED_NUM;
if (position < 0) position += LED_NUM;
if (position == 0 && direction == -1) direction = 1;
if (position == LED_NUM - bar_length - gap && direction == 1) direction = -1;
counter++;
} while (iterations == 0 || counter < iterations);
}
/**
* @brief 单向流水灯效果
* @param color: 流动颜色 (GRB格式)
* @param speed: 效果速度 (1-100)
* @param iterations: 迭代次数 (0=永久)
*/
void Effect_WaterFlow(uint32_t color, uint8_t speed, uint16_t iterations)
{
uint16_t counter = 0;
do {
for (int i = 0; i < LED_NUM; i++) {
WS2812B_Clear();
WS2812B_SetPixel(i, color);
WS2812B_Show();
Delay_ms(50 - speed/2);
}
counter++;
} while (iterations == 0 || counter < iterations);
}
/**
* @brief 双向流水灯效果
* @param color: 流动颜色 (GRB格式)
* @param speed: 效果速度 (1-100)
* @param iterations: 迭代次数 (0=永久)
*/
void Effect_BidirectionalFlow(uint32_t color, uint8_t speed, uint16_t iterations)
{
uint16_t counter = 0;
do {
// 从左向右
for (int i = 0; i < LED_NUM; i++) {
WS2812B_Clear();
WS2812B_SetPixel(i, color);
WS2812B_Show();
Delay_ms(50 - speed/2);
}
// 从右向左
for (int i = LED_NUM - 2; i > 0; i--) {
WS2812B_Clear();
WS2812B_SetPixel(i, color);
WS2812B_Show();
Delay_ms(50 - speed/2);
}
counter++;
} while (iterations == 0 || counter < iterations);
}
/******************************* 辅助函数 *******************************/
/**
* @brief HSV转换为RGB(GRB格式)
* @param h: 色调 (0-359)
* @param s: 饱和度 (0-255)
* @param v: 明度 (0-255)
* @return GRB格式的颜色值
*/
static uint32_t HSVtoRGB(uint16_t h, uint8_t s, uint8_t v)
{
uint8_t r, g, b;
uint8_t region;
uint8_t p, q, t;
uint32_t f;
if (s == 0) {
r = g = b = v;
return ((uint32_t)g << 16) | ((uint32_t)r << 8) | b;
}
// 将色调映射到0-255范围
h %= 360;
f = h * 255;
f /= 60;
region = f / 255;
p = (v * (255 - s)) >> 8;
q = (v * (255 - ((s * f) >> 8))) >> 8;
t = (v * (255 - ((s * (255 - f)) >> 8))) >> 8;
switch (region) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
default: r = v; g = p; b = q; break;
}
return ((uint32_t)g << 16) | ((uint32_t)r << 8) | b;
}
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
/**
* @brief 单条音乐频谱跳动效果
* @param base_color: 基础颜色(GRB格式)
* @param speed: 效果速度(1-100)
* @param iterations: 迭代次数(0=永久)
*/
void Effect_SingleMusicBar(uint32_t base_color, uint8_t speed, uint16_t iterations)
{
uint16_t counter = 0;
uint8_t current_height = 0; // 当前高度 (0-100%灯珠)
uint8_t target_height = 30; // 目标高度
uint8_t decay_counter = 10; // 衰减倒计时
do {
WS2812B_Clear();
// 更新高度
if (current_height < target_height) {
// 向上增长
current_height = MIN(target_height, current_height + 5);
} else if (current_height > target_height) {
// 向下衰减
current_height = MAX(target_height, current_height - 3);
} else {
// 达到目标高度后开始衰减倒计时
if (--decay_counter <= 0) {
// 生成新的随机高度 (5%-100%)
target_height = 5 + rand() % 95;
// 重置衰减计时器 (10-30次更新)
decay_counter = 10 + rand() % 20;
}
}
// 计算实际点亮的灯珠数量
uint8_t num_leds = current_height * LED_NUM / 100;
if (num_leds > LED_NUM) num_leds = LED_NUM;
// 点亮灯珠
for (int i = 0; i < num_leds; i++) {
// 基础颜色
uint32_t color = base_color;
// 顶部高亮效果 (最高的10%灯珠变为绿色)
if (i > num_leds * 0.9) {
color = COLOR_GREEN;
}
// 颜色渐变效果 (高度越高颜色越亮)
else {
// 提取基础颜色分量
uint8_t g = (base_color >> 16) & 0xFF;
uint8_t r = (base_color >> 8) & 0xFF;
uint8_t b_col = base_color & 0xFF;
// 根据位置增加亮度 (线性渐变)
uint8_t boost = i * 255 / num_leds;
g = MIN(255, g + boost);
r = MIN(255, r + boost);
b_col = MIN(255, b_col + boost);
color = (g << 16) | (r << 8) | b_col;
}
WS2812B_SetPixel(i, color);
}
WS2812B_Show();
Delay_ms(30 - speed/3); // 速度调整 (0-100映射到30-0ms)
counter++;
} while (iterations == 0 || counter < iterations);
}
HDL_WS2812B.h文件
/*******************************************************************************
* @file HDL_WS2812B.h
* @author
* @version V1.0
* @date 2025
* @brief Improved WS2812B driver with multiple effects
******************************************************************************/
#ifndef _HDL_WS2812B_H
#define _HDL_WS2812B_H
#include "stm32f10x.h"
#define WS2812B_PIN GPIO_Pin_1
#define WS2812B_PORT GPIOA
#define WS2812B_HIGH GPIO_SetBits(WS2812B_PORT,WS2812B_PIN)
#define WS2812B_LOW GPIO_ResetBits(WS2812B_PORT,WS2812B_PIN)
/* 根据DataSheet定义0/1编码对应的高电平比较值 */
#define WS2812B_ARR 90 // TIM2的自动重装载值
#define T0H 30 // 0编码高电平时间
#define T1H 60 // 1编码高电平时间
/* 灯珠数量 */
#define LED_NUM 60
#define DATA_SIZE 24 // WS2812B一个编码的bit数
/* 单个灯珠的编码对应的比较值数组 */
extern uint16_t Single_LED_Buffer[DATA_SIZE * LED_NUM];
/* 存储所有灯珠的颜色数据 (GRB格式) */
extern uint32_t LED_Color[LED_NUM];
/* 颜色定义 (GRB格式) */
#define COLOR_RED 0x00FF00 // 红色
#define COLOR_GREEN 0xFF0000 // 绿色
#define COLOR_BLUE 0x0000FF // 蓝色
#define COLOR_YELLOW 0xFFFF00 // 黄色
#define COLOR_WHITE 0xFFFFFF // 白色
#define COLOR_PURPLE 0x00FF80 // 紫色
#define COLOR_CYAN 0xFFFF80 // 青色
void PWM_WS2812B_Init(uint16_t arr);
void WS2812B_Reset(void);
void WS2812B_Encode(void);
void WS2812B_Show(void);
void WS2812B_SetPixel(uint16_t index, uint32_t color);
void WS2812B_SetAll(uint32_t color);
void WS2812B_Clear(void);
/* 显示效果函数 */
void Effect_RainbowWave(uint8_t speed, uint16_t iterations);
void Effect_Breathe(uint32_t color, uint8_t speed, uint16_t iterations);
void Effect_ColorCycle(uint8_t speed, uint16_t iterations);
void Effect_RunningLights(uint32_t color, uint8_t width, uint8_t speed, uint16_t iterations);
void Effect_Flash(uint32_t color1, uint32_t color2, uint8_t speed, uint16_t flashes);
void Effect_WhiteFade(uint8_t brightness, uint8_t speed, uint16_t iterations);
void Effect_RandomTwinkle(uint8_t speed, uint16_t flashes);
void Effect_JumpingBar(uint32_t color, uint8_t bar_length, uint8_t gap, uint8_t speed, uint16_t iterations);
void Effect_WaterFlow(uint32_t color, uint8_t speed, uint16_t iterations);
void Effect_BidirectionalFlow(uint32_t color, uint8_t speed, uint16_t iterations);
void Effect_SingleMusicBar(uint32_t base_color, uint8_t speed, uint16_t iterations);
#endif