- 近期用RGB三色灯WS2812B做了个彩虹灯的小玩意,记录下使用过程
- 网上文档等资料都很齐全,在此不再具体介绍此IC (开头带WS2812B的文档资料)
芯片&工具
- STM32F030
- STM32CubeMX
- IAR
编码
- 使用CubeMX初始化TIM3的Channel4作为PWM的DMA输出功能
1. 外设初始化配置
- 根据文档指明的时序生成正确的GRB数据通过PWM发给LED灯珠
2. 让灯亮起来
#define RED_INDEX 0
#define GREEN_INDEX 1
#define BLUE_INDEX 2
#
define LED_NUM 4
#define GRB_BIT 24
#define TIMING_ONE 40
#define TIMING_ZERO 18
uint16_t LED_BYTE_Buffer[300];
void WS281x_Show(uint16_t send_len)
{
HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_4, (uint32_t *)&LED_BYTE_Buffer, send_len);
}
void WS2812_send(uint8_t *rgb, uint16_t len)
{
uint8_t i;
uint16_t memaddr = 0;
uint16_t buffersize;
buffersize = len * GRB_BIT;
while (len)
{
for(i=0; i<8; i++)
{
LED_BYTE_Buffer[memaddr] = ((rgb[GREEN_INDEX]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
memaddr++;
}
for(i=0; i<8; i++)
{
LED_BYTE_Buffer[memaddr] = ((rgb[RED_INDEX]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
memaddr++;
}
for(i=0; i<8; i++)
{
LED_BYTE_Buffer[memaddr] = ((rgb[BLUE_INDEX]<<i) & 0x0080) ? TIMING_ONE:TIMING_ZERO;
memaddr++;
}
len--;
}
WS281x_Show(memaddr);
}
int main(void)
{
uint8_t color_red[] = {255, 0, 0};
...
MX_GPIO_Init();
MX_DMA_Init();
MX_TIM3_Init();
...
WS2812_send(color_red, LED_NUM);
}
- 把RGB光谱的红色->紫色->红色模拟遍历一遍
- 每个色值被显示后会有一点延迟使彩虹灯细节明显,每个阶段结束也有一定延迟来突出每一个色域
- 延迟可以自行调整,但延迟过大会有LED明显闪烁的情况
3. 显示彩虹灯
#define PROCESS_DELAY 5
#define SECTION_DELAY 100
void Rainbow_Flow(void)
{
uint8_t state = 1;
uint8_t RGBList[3] = {255, 0, 0};
while(1)
{
if (退出彩虹灯的条件为真(如按键等))
{
break;
}
for(uint8_t cnt = 0; cnt < (255-1); cnt++)
{
switch (state)
{
case 1:
RGBList[GREEN_INDEX] = cnt;
break;
case 2:
RGBList[RED_INDEX] = 255 - cnt;
break;
case 3:
RGBList[BLUE_INDEX] = cnt;
break;
case 4:
RGBList[GREEN_INDEX] = 255 - cnt;
break;
case 5:
RGBList[RED_INDEX] = cnt;
break;
case 6:
RGBList[BLUE_INDEX] = 255 - cnt;
break;
default:
break;
}
SysDelay_Xms(PROCESS_DELAY);
WS2812_send(RGBList, LED_NUM);
}
if (state < 6)
state++;
else
state = 1;
SysDelay_Xms(SECTION_DELAY);
}
}
4. 享受彩虹灯