基于STM32的WS2812B炫彩灯光控制系统

基于STM32的WS2812B炫彩灯光控制系统

这个项目是一个高效稳定的WS2812B RGB LED灯带驱动库,专为STM32F103系列微控制器设计。通过PWM和DMA技术实现精确的时序控制,支持多达60个LED灯珠,提供了丰富的灯光效果和灵活的配置选项。

效果图

(只拍摄了部分效果)

在这里插入图片描述

核心功能亮点

  1. 专业级硬件驱动

    • 零等待DMA传输技术
    • 自动生成WS2812B协议波形(800kHz)
    • 精确的复位信号控制(>50μs低电平)
  2. 11种炫彩特效

    // 彩虹波浪效果
    Effect_RainbowWave(8, 3);
    // 呼吸灯效果
    Effect_Breathe(COLOR_BLUE, 50, 5);
    // 奔跑光带
    Effect_RunningLights(COLOR_GREEN, 25, 80, 5);
    // 音乐频谱效果
    Effect_SingleMusicBar(COLOR_RED, 75, 500);
    
  3. 卓越的性能优化

    • 呼吸灯查表算法替代浮点运算
    • HSV转RGB快速转换函数
    • 内存占用优化(双缓冲设计)
    • 动态延时控制技术

技术架构

DMA通道
精确波形
GRB格式
STM32F10x
TIM2_PWM
WS2812B_LED
Driver
Color_Processing
HSV_RGB_Converter
Effects_Engine
Dynamic_Delay

关键特性

  • 物理层

    • 工作电压:灯珠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);
}

应用场景

  1. 智能家居氛围照明
  2. 音乐可视化系统
  3. 节日装饰灯光
  4. 汽车氛围灯
  5. 游戏设备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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九层指针

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值