电子说
WS2812是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED灯珠相同,每个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路,还包含有高精度的内部振荡器和12V高压可编程定电流控制部分,有效保证了像素点光的颜色高度一致。
数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。像素点采用自动整形转发技术,使得该像素点的级联个数不受信号传送的限制,仅仅受限信号传输速度要求。
LED具有低电压驱动,环保节能,亮度高,散射角度大,一致性好,超低功率,超长寿命等优点。将控制电路集成于LED上面,电路变得更加简单,体积小,安装更加简便。

| VCC | 输入电压正极 |
|---|---|
| GND | 输入电压负极 |
| DI | 数据输入 |
| DO | 数据输出,与下一联级的DI连接 |



通过上述工作原理与协议解读,在有多个led级联的情况下,先发送第一个led的数据,后第二个、第三个、以此类推。
1.引脚接线
| STM32F103C8T6 | WS2812 |
|---|---|
| 5V | 5V,注意:如果多个级联要外接电源,不要用单片机的5V |
| GND | GND |
| PA0 | DI |
| 2. 代码示例 | |
| WS2812.c |
#include "ws2812.h"
void WS2812_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
DMA_InitTypeDef DMA_InitStructure;
//使能 TIM2、DMA1 和 GPIOA 时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // TIM2 定时器时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // DMA1 总线时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // GPIOA 时钟
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 90 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; //CCR
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
DMA_DeInit(DMA1_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM2- >CCR1;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)My_ws_buf;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 0;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Channel2, &DMA_InitStructure);
TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);
}
/**
* @brief 设置单颗 WS2812B 灯的 RGB 颜色(十进制 0–255)
* @param r 红色分量,0 表示关闭,255 表示最大亮度
* @param g 绿色分量,0 表示关闭,255 表示最大亮度
* @param b 蓝色分量,0 表示关闭,255 表示最大亮度
*/
void WS2812B_SetColor(uint32_t r, uint32_t g, uint32_t b)
{
uint16_t *p = My_ws_buf;
uint32_t mask, rep, bit;
uint32_t GRB_Data;
GRB_Data = ((g & 0xFFU) < < 16)
| ((r & 0xFFU) < < 8)
| (b & 0xFFU);
for (rep = 0; rep < LED_REPEAT; rep++) {
mask = 1UL < < (BITS_PER_LED - 1);
for (bit = 0; bit < BITS_PER_LED; bit++, mask > >= 1) {
*p++ = (GRB_Data & mask) ? WS2812_HIGH : WS2812_LOW;
}
}
}
//发送信号
void WS2812B_Send(void)
{
//清除 DMA 标志、重载传输长度
DMA_ClearFlag(DMA1_FLAG_TC2);
DMA_SetCurrDataCounter(DMA1_Channel2, LED_REPEAT * BITS_PER_LED);
//启动 DMA & 定时器
DMA_Cmd(DMA1_Channel2, ENABLE);
TIM_Cmd(TIM2, ENABLE);
//等待传输完成
while (!DMA_GetFlagStatus(DMA1_FLAG_TC2));
//关闭 TIM & DMA 并清标志,产生 >50μs 复位低电平
TIM_Cmd(TIM2, DISABLE);
DMA_Cmd(DMA1_Channel2, DISABLE);
DMA_ClearFlag(DMA1_FLAG_TC2);
}
void ws2812_OFF(void)
{
WS2812B_SetColor(0, 0, 0);
WS2812B_Send();
}
main.c
#include "stm32f10x.h" // Device header
#include "ws2812.h"
#include "delay.h"
static const uint8_t color_list[][3] = {
{255, 0, 0}, // 红
{255, 125, 0}, // 橙
{255, 255, 0}, // 黄
{ 0, 255, 0}, // 绿
{ 0, 255, 255}, // 青
{ 0, 0, 255}, // 蓝
{255, 0, 255}, // 紫
{ 0, 0, 0} // 关灯
};
uint16_t NUM_COLORS = sizeof(color_list) / sizeof(color_list[0]);
uint32_t idx = 0;
int main(void)
{
WS2812_Init();
// ws2812_OFF();
while(1){
uint8_t r = color_list[idx][0];
uint8_t g = color_list[idx][1];
uint8_t b = color_list[idx][2];
WS2812B_SetColor(r, g, b);
WS2812B_Send();
Delay_ms(1000);
idx = (idx + 1) % NUM_COLORS;
}
}

WS2812 是一款将控制电路、信号整形放大和恒流驱动与 RGB 发光单元集成于 5050 封装中的智能化全彩 LED 模块,仅需一根数据线即可以 800 kbps 单线协议传输精确的色彩控制信号,从而实现链式级联上千点的独立寻址与显示。内部集成的数字移位寄存器与精密振荡器可按 GRB 顺序(G7…G0→R7…R0→B7…B0)接收并锁存 24 bit 颜色数据,随后通过恒流驱动电路根据不同位的高低电平宽度产生对应亮度,并将余下数据重塑后输出到下一颗,实现信号级联。可广泛应用于灯带、灯环、可穿戴灯效、舞台装饰等场景。
注意事项:
以上仅为个人观点供参考,如有问题欢迎大家留言讨论,如需源码可点赞收藏加关注,在评论留下邮箱获取!!!
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !