WS2812B灯带

news/2024/11/23 9:26:18/

 开发WS2812B灯带笔记


目录

什么是WS2812B灯

WS2812B灯带连接原理图

WS2812B灯带的数据和数据传输是啥样的?

补充:什么是RGB?

那么WS2812B灯的24bit数据如何构造?

WS2812B灯的逻辑“1”和逻辑“0”

代码部分

实现ns级别延时


什么是WS2812B灯

WS2812B是一种智能控制LED光源,将控制电路和RGB芯片集成在5050个元件包中。其内部包括智能数字端口数据锁存器和信号重塑放大驱动电路。还包括精密内部振荡器和电压可编程恒流控制部分,有效地确保像素点光色高度一致。俗称IC灯。

WS2812B灯带连接原理图

主要通过一条数据线来控制每个灯的颜色 ,每个灯珠控制着下个灯珠。

WS2812B灯带的数据和数据传输是啥样的?

数据传输协议采用单一的NZR通信模式。在像素通电复位后,DIN端口从控制器接收数据,第一个像素收集初始24位数据,然后发送到内部数据锁存器,其他数据通过内部信号重塑放大电路的重塑,通过DO端口发送到下一个级联像素。在对每个像素进行传输后,该信号减少24位。像素采用自动整形传输技术,使像素级联数不限制信号的传输,只依赖于信号传输的速度。

通俗点讲,就是每个灯接受24位的数据为每个灯的颜色像素(RGB888)。比如,你发送了3组24位的数据,第一个灯珠接收了第一组24位数据后,会把后面的两组数据发给第二个灯珠,第二个灯珠接受了第二组24位数据后,会把第三组数据发给第三个灯珠,以此类推。

灯珠接受的24位数据按图里来看,是8位绿色,8位红色,8位蓝色组成。

补充:什么是RGB?

RGB颜色空间以R(Red:红)、G(Green:绿)、B(Blue:蓝)三种基本色为基础,进行不同程度的叠加,产生丰富而广泛的颜色,所以俗称三基色模式。

RGB空间是生活中最常用的一个颜色显示模型,电视机、电脑的CRT显示器等大部分都是采用这种模型。自然界中的任何一种颜色都可以由红、绿、蓝三种色光混合而成,现实生活中人们见到的颜色大多是混合而成的色彩。

肉眼可以识别世界上的所有颜色,而RGB几乎可以组合成世界上所有的颜色!

以我们所用的RGB24为例,RGB24的每个元素在计算机内存中占用1个字节,1个字节等于8个bit位,所以RGB每个元素的取值范围为:0~255。

那么三色组合起来256x256x256=16777216(一千六百七十七万七千二百一十六)种颜色。

那么WS2812B灯的24bit数据如何构造?


既然是24bit数据代表三种颜色,我们就要首先知道一个bit的意义是什么,我们传统意义上来说1个bit代表一个数据位,但是对于数据位bit的理解好像就是“1”或者“0”在数电里我们很容易把高低电平跟逻辑1和逻辑0对应起来,但是表示灯珠的逻辑电平不是简单的高低电平。在数值上0xFFFFFF就是24bit的1,0x000000就是24bit的0.这里有8个bit代表颜色G分量,G7G6G5G4G3G2G1G0,有8个bit代表R分量R7R6R5R4R3R2R1R0,有8个bit代表B分量B7B6B5B4B3B2B1B0,当不同分量组合时候就会有不同的数据产生,这个数据背后其实是逻辑电平。

但是我们IC灯的逻辑“1”并不是简简单单的高电平,IC灯的逻辑“0”也不是简简单单的低电平。

 

WS2812B灯的逻辑“1”和逻辑“0”

 从上图可知,逻辑“1”和逻辑“0”并不是普通的高电平,低电平。而是由高低电平不同比例组成的。

逻辑“0”:由小部分的高电平和大部分的低电平组成 

逻辑“1”:由大部分的高电平和小部分的低电平组成

下面讲讲这大部分和小部分的精确取值:

 逻辑“0”:由220ns-380ns的高电平和580ns-1us的低电平组成

逻辑“1”:由由220ns-380ns的低电平和580ns-1us的高电平组成

代码部分

到这我们差不多就知道了WS2812B灯的原理和时序了,下面讲讲编程的部分。

实现ns级别延时

  1. 硬件延时NOP实现
  2. 滴答定时器中断实现
  3. 普通定时器实现

首先因为对时序要求比较严格,所以需要实现ns级别的延时。

我用的板子是gd32f450,系统频率是200mhz。

1/200Mhz = 0.005 ms = 5 ns

所以一个nop的延时是5ns。

#define DELAY_5ns	__NOP() /* 一个nup为5ns		1/200Mhz = 0.005 ms = 5 ns*/
#define DELAY_50ns  DELAY_5ns;DELAY_5ns;DELAY_5ns;DELAY_5ns;DELAY_5ns;DELAY_5ns;DELAY_5ns;DELAY_5ns;DELAY_5ns;DELAY_5ns
#define DELAY_250ns	DELAY_50ns;DELAY_50ns;DELAY_50ns;DELAY_50ns;DELAY_50ns
#define DELAY_300ns	DELAY_50ns;DELAY_50ns;DELAY_50ns;DELAY_50ns;DELAY_50ns;DELAY_50ns
#define DELAY_600ns	DELAY_300ns;DELAY_300ns

编写逻辑“0”和逻辑“1”的函数

void Bit_0(void)
{rt_pin_write(IC_LED_GREEN_REG,1);DELAY_300ns;rt_pin_write(IC_LED_GREEN_REG,0);DELAY_600ns;
}
void Bit_1(void)
{rt_pin_write(IC_LED_GREEN_REG,1);DELAY_600ns;rt_pin_write(IC_LED_GREEN_REG,0);DELAY_300ns;
}

最简单的驱动函数

void RGB_Set(void)
{for(uint8_t i = 0;i<8;i++){Bit_1();}for(uint8_t i = 0;i<8;i++){Bit_0();}for(uint8_t i = 0;i<8;i++){Bit_0();}
}

这样就生成了24bit的数据,111111110000000000000000,绿灯

但是这样的操作方法显然不适合在项目里使用,所以我们要写一些函数来设置

比如我们一般是按RGB值来设定灯的颜色,我们输入RGB三颜色的值就可以。但是这样的话又会又一个问题,我们输入的是10进制的值,0-255。但是我们所需要的却是需要把这个值换成2进制,因此,需要根据这些来编写代码

首先需要控制函数,以后项目需要控制IC灯只需要调用这个函数输入相对应的RGB值就行了,

int ic_led_ctrl(int r_val, int g_val, int b_val) 
{decimal_to_binary(r_val,g_val,b_val);return 0;
}

接着我们要实现把10进制的RGB值转化为2进制的RGB值

/* 连接数组 */
int connection_arr(int *r,int *g,int *b)
{int i = 1;int *rgb = rgb_arr;while (i <= 8){*rgb = *g;rgb++;g++;i++;}while (i <= 16){*rgb = *r;rgb++;r++;i++;}while (i <= 24){*rgb = *b;rgb++;b++;i++;}return 0;
}/* 反转数组 */
int reverse(int *x) {int* p, temp, * i, * j;int	m = (8 - 1) / 2;i = x;    		/* 数组首元素地址 */j = x + 8 - 1;	/* 数组末尾元素地址 */p = x + m;		/* 中间元素地址 */for (i = x; i <= p; ++i, --j) {temp = *i;*i = *j;*j = temp;}return 0;
}
/* 十进制转换成二进制 */
static void decimal_to_binary(int r_num,int g_num, int b_num)
{int r_arr[8] = {0}; /* 用一个长度为32的数组接收最后的二进制数,里面的0是为数组设置初始值 */int g_arr[8] = {0};int b_arr[8] = {0};int index = 0;/* 用来定义数组的下标 */r_arr[index] = r_num % 2; /* 先获取输入数字的第一个二进制位 */g_arr[index] = g_num % 2;b_arr[index] = b_num % 2;index++; /* 下标下移一位 */while (1) {/* 使用while循环来获取剩下的二进制位 *//*十进制转换为二进制思想:1.对十进制数进行除以2的操作2.对所获得的商进行取余的操作,所获得的数就是二进制每一位3.当num<2时,即num除以二不会再有大于1的数字,num%2必为0时此时说明num已经完全转换位二进制数,则跳出循环*/r_num = r_num / 2;g_num = g_num / 2;b_num = b_num / 2;r_arr[index] = r_num % 2;g_arr[index] = g_num % 2;b_arr[index] = b_num % 2;index++;if (g_num < 2 && r_num <2 && b_num < 2){break;}			}		reverse(r_arr);reverse(g_arr);reverse(b_arr);connection_arr(r_arr,g_arr,b_arr);
}

十进制转换二进制代码详解,请点击观看

当做完上面这些,我们只需要在主函数中写入RGB的值就能实现灯带的点亮了。

void RGB_Set(void)
{int i = 0;for(i = 0; i < 24; ++i) {if(rgb_arr[i] == 1){Bit_1();} else {Bit_0();}}}


http://www.ppmy.cn/news/585356.html

相关文章

最新版青龙面板V2.15.0略微详细安装教程

目录 操作前我们要明白什么是青龙面板&#xff1f; 准备工作&#xff1a; 1.首先进入宝塔面板&#xff0c;安装Docker为接下来做准备&#xff1a; 2.安装青龙面板 3.青龙面板基础命令 4.拉取各种库的脚本如下 5.获取京东cookie 6.添加Cookie 操作前我们要明白什么是青龙…

UnityShader35:光晕光效

一、光晕逻辑 光晕的逻辑很简单&#xff0c;就是在屏幕上画上一个一个方形的 Mesh&#xff0c;然后采样带 Alpha 通道的光晕贴图&#xff0c;效果就出来了&#xff0c;其中方形 Mesh 的大小、位置、纹理表现全部都由美术配置&#xff0c;因此效果好坏主要取决于光晕贴图以及是…

FL STUDIO 20.8中文汉化版完美支持中文语言

FL Studio 简称FL&#xff0c;全称&#xff1a;Fruity Loops Studio&#xff0c;因此国人习惯叫它"水果"。目前最新版本(包括测试版本)是FL studio 20.8&#xff0c;它让你的计算机就像是全功能的录音室&#xff0c;大混音盘&#xff0c;让你的音乐突破想象力的限制。…

npm发布自己的公网包步骤详解

初始化项目 比如我&#xff0c;创建了code-transfor-text_vue项目 根目录初始化git git init .建立开源协议 给项目根目录手动创建LICENSE文件文件&#xff0c;没有后缀名 MIT LicenseCopyright (c) 2023 quanyiPermission is hereby granted, free of charge, to any pers…

mysql5.6 linux 安装设置密码和远程登录

mysql 设置跳过登陆验证&#xff1a; vim /etc/my.cnf文件&#xff1b; 在[mysqld]后添加skip-grant-tables&#xff08;登录时跳过权限检查) [mysqld]skip-grant-tables port 3306 socket /tmp/mysql.sock datadir /www/server/data default_storage_engin…

力扣-线段树

力扣-线段树 307. 区域和检索 - 数组可修改 我的题解&#xff1a; 思路: 直接套用线段树模版&#xff0c;第一个用的是数组模拟树&#xff0c;第二个用节点来实现 public class NumArray {//数组的长度private int n;//输入的数组private int[] arr;//存储元素值private int[] …

项目管理“铁三角”

项目管理“铁三角” 项目的范围管理、时间管理、成本管理构成了决定项目成败&#xff08;一般以项目的质量作为评估依据&#xff09;的“铁三角”。范围扩大&#xff0c;要通过增加项目的时间与成本保证项目的质量&#xff0c;或者通过降低质量要求以符合时间或者成本的要求&a…

linux铁三角视频,linux常用命令cdlsPATH

一、cd 命令 cd--change directory即变换目录。 cd 绝对路径或相对路径 cd ~用户 表示到这个用户的家目录&#xff0c;即/home/用户 cd ~表示回到自己的家目录&#xff0c;即/root这个目录 cd 表示回到自己的家目录 cd .. 表示回到上次目录 二、ls命令 ls--list即列出当前目录下…