1. 控制方式
WS2812B数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。
2. 输入码型
每一次传数据前,需要先给个复位信号,如下图所示。
然后依次是每个灯的24bit数据,且写入24bit位数据的排序方式为:G -> R -> B ,如下图所示。
而每个 bit 位的表示方式为:(高电平+低电平)时间,如下图所示。
3. 典型电路
4. 部分代码
完整单片机代码:https://download.csdn.net/download/qq_26043945/89657851
#include "WS2812B.h"
uint32_t GRB[]={0x00FF00,0x00FF19,0x00FF32,0x00FF4B,0x00FF64,0x00FF7D,0x00FF96,0x00FFAF,0x00FFC8,0x00FFE1,
0x00FFFF,0x00E1FF,0x00C8FF,0x00AFFF,0x0096FF,0x007DFF,0x0064FF,0x004BFF,0x0032FF,0x0019FF,
0x0000FF,0x1900FF,0x3200FF,0x4B00FF,0x6400FF,0x7D00FF,0x9600FF,0xAF00FF,0xC800FF,0xE100FF,
0xFF00FF,0xFF00E1,0xFF00C8,0xFF00AF,0xFF0096,0xFF007D,0xFF0064,0xFF004B,0xFF0032,0xFF0019,
0xFF0000,0xFF1900,0xFF3200,0xFF4B00,0xFF6400,0xFF7D00,0xFF9600,0xFFAF00,0xFFC800,0xFFE100,0xFFFF00};
__IO uint32_t WS2812_buf[LED_Num]={0};
__IO uint32_t GRB_buf[LED_Num]={0};
//用于确定现在传输的是哪一个灯珠的数据
__IO uint32_t ws2812b_num=0;
//用于ws2812灯带的每1灯的24位数据进行提取
__IO uint32_t ws2812b_num_bit=0x800000;
//用于ws2812灯带的复位计数
uint8_t ws2812b_rst_num=0;
void ws2812_close(void){
ws2812_stop();
for(uint32_t x=0;x<LED_Num;x++){
WS2812_buf[x] = 0x000000;
}
ws2812_run();
}
void ws2812_stop(void){
ws2812_hal_stop;
ws2812b_num=0;
ws2812b_num_bit=0x800000;
__HAL_TIM_SET_COMPARE(ws2812b_Tim, ws2812b_Channel, 0);
HAL_Delay(1);
}
void ws2812_run(void){
ws2812_hal_run;
}
void ws2812b_G_R_B_all(uint8_t num, uint8_t brigh){
uint8_t r,g,b;
if(num==0){
g = 0x00ff00/65536;
r = 0x00ff00%65536/256;
b = 0x00ff00%256;
for(uint32_t x=0;x<LED_Num;x++){
WS2812_buf[x] = ((uint8_t)(g*(0.0039*brigh)))*65536+((uint8_t)(r*(0.0039*brigh)))*256+((uint8_t)(b*(0.0039*brigh)));
}
}else if(num==1){
g = 0xff0000/65536;
r = 0xff0000%65536/256;
b = 0xff0000%256;
for(uint32_t x=0;x<LED_Num;x++){
WS2812_buf[x] = ((uint8_t)(g*(0.0039*brigh)))*65536+((uint8_t)(r*(0.0039*brigh)))*256+((uint8_t)(b*(0.0039*brigh)));
}
}else if(num==2){
g = 0x0000ff/65536;
r = 0x0000ff%65536/256;
b = 0x0000ff%256;
for(uint32_t x=0;x<LED_Num;x++){
WS2812_buf[x] = ((uint8_t)(g*(0.0039*brigh)))*65536+((uint8_t)(r*(0.0039*brigh)))*256+((uint8_t)(b*(0.0039*brigh)));
}
}
}
void ws2812b_while_all(uint8_t num, uint8_t brigh){
uint8_t size = sizeof(GRB) / sizeof(GRB[0]); // 计算数组长度
uint8_t r,g,b;
uint32_t buf = GRB[num%size];
g = buf/65536;
r = buf%65536/256;
b = buf%256;
for(uint8_t x=0;x<LED_Num;x++){
WS2812_buf[x] = ((uint8_t)(g*(0.0039*brigh)))*65536+((uint8_t)(r*(0.0039*brigh)))*256+((uint8_t)(b*(0.0039*brigh)));
}
}
void ws2812b_while_all1(uint8_t num, uint8_t brigh){
uint8_t r,g,b;
uint8_t size = sizeof(GRB) / sizeof(GRB[0]); // 计算数组长度
uint32_t buf = GRB[0]; // 保存第一个元素
// 将每个元素向前移动一个位置
for (uint8_t i = 1; i < size; i++) {
GRB[i - 1] = GRB[i];
}
// 将第一个元素放到最后一个位置
GRB[size - 1] = buf;
for(uint32_t x=0;x<LED_Num;x++){
uint8_t size = sizeof(GRB) / sizeof(GRB[0]); // 计算数组长度
uint8_t i = x*num%size;
g = GRB[i]/65536;
r = GRB[i]%65536/256;
b = GRB[i]%256;
WS2812_buf[x] = ((uint8_t)(g*(0.0039*brigh)))*65536+((uint8_t)(r*(0.0039*brigh)))*256+((uint8_t)(b*(0.0039*brigh)));
}
}
void ws2812b_while_all2(uint8_t num, uint8_t brigh){
uint8_t r,g,b;
uint8_t size = sizeof(GRB) / sizeof(GRB[0]); // 计算数组长度
uint32_t buf = GRB[size - 1]; // 保存最后一个元素
// 将每个元素向后移动一个位置
for (uint8_t i = size - 1; i > 0; i--) {
GRB[i] = GRB[i - 1];
}
// 将最后一个元素放到第一个位置
GRB[0] = buf;
for(uint32_t x=0;x<LED_Num;x++){
uint8_t size = sizeof(GRB) / sizeof(GRB[0]); // 计算数组长度
uint8_t i = x*num%size;
g = GRB[i]/65536;
r = GRB[i]%65536/256;
b = GRB[i]%256;
WS2812_buf[x] = ((uint8_t)(g*(0.0039*brigh)))*65536+((uint8_t)(r*(0.0039*brigh)))*256+((uint8_t)(b*(0.0039*brigh)));
}
}
void ws2812b_rst(void){
__HAL_TIM_SET_COMPARE(ws2812b_Tim, ws2812b_Channel, 0);
ws2812b_rst_num++;
if(ws2812b_rst_num>15){
ws2812b_rst_num=0;
ws2812b_num=0;
for(uint8_t x=0;x<LED_Num;x++){
GRB_buf[x] = WS2812_buf[x];
}
}
}
uint32_t ws2812_buf=0;
void ws2812b_set(void){
if(ws2812b_num==LED_Num){
ws2812b_rst();
}else{
ws2812_buf = GRB_buf[ws2812b_num];
if(ws2812_buf&ws2812b_num_bit){
ws2812b_set_1;
}else{
ws2812b_set_0;
}
ws2812b_num_bit = ws2812b_num_bit>>1;
if(ws2812b_num_bit==0x000000){
ws2812b_num++;
ws2812b_num_bit = 0x800000;
}
}
}
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » 控制WS2812B实例代码(新_PWM方式)
发表评论 取消回复