电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
使用一根数据线控制全彩LED灯!单总线LED使用指南
分 享
扫描二维码分享
使用一根数据线控制全彩LED灯!单总线LED使用指南
LED
51
WS812
7566396fd9acf5af
关注
发布时间: 2019-07-18
丨
阅读: 3295
相信大家学习单片机的第一课就是点亮第一盏LED灯了吧,初次点亮LED的时候的心情肯定是很激动的,可以操控眼前这个小小的芯片完成自己编写的指令,顿时感觉到很奇妙。初次了解之后便会激发我们的探索精神,当学习了PWM之后,控制RGB彩灯随意调出千变万化的颜色肯定不再是难事,用在各种项目上,RGB灯会让作品更加鲜艳动人。在这美丽的背后,其实隐藏了很多的科学道理,RGB灯的颜色能千变万化的原因是因为其内部集成了3个独立的3原色灯珠,然后使用PWM波控制每个灯珠处在不同的亮度,便可以得到不同的色彩。但是一个RGB灯可能会占用多个端口,想控制很多个RGB灯便是有些难度,好在随着集成工艺的发展,这一切不再是问题,如今的工艺促使了一种新型灯珠的出现,那就是单总线LED。 ------------ 简单点来说就是这种类型的灯珠内置了一个驱动电路,它控制着灯珠发出的颜色,并且有一个数据输入口,意味着我们可以往在这个灯珠里面输入数据,然后灯珠内部的电路就会驱动的灯珠发出我们想要的颜色。这个电路呢还有一个数据的输出口,也就是说它可以将接受到的数据再次发送出去,送给下一个灯珠的输入,所以这使得所有的灯珠都可以连在一起,只需要使用一个IO口控制,这就相比传统的RGB灯节省了很多的端口。 这种类型的灯珠主要的核心就在它里面集成的那样一个驱动电路,这种类型的驱动电路有很多种,例如常见的WS2811,2812,SK6812等等,所以用其制作完成的灯珠一般都使用驱动电路的名字来命名。对于灯珠的大小型号呢,则有很多种类,例如5050,3535以及2020等封装,大家搜索的时候,搜索驱动电路的型号加上封装型号就可以找到想要的单总线LED了。下面是WS2812采用5050封装的图片。 ![](https://cf03.ickimg.com/bbsimages/201907/75d1551485bc534452a9cbce3121319d.png) 本文会就WS2812这款最常用的驱动芯片来讲解其的控制方法以及在最后我会写一些控制这类单总线LED的方法。 由于是单总线通讯,自然没有时钟信号线,所以通讯的时序变得非常重要,我找到一份WS2812的数据手册,查看到了其中提到的输入数据时序图。 ![](https://cf03.ickimg.com/bbsimages/201907/2a5fe80c32bb1948673e441ab6bbe51a.png) ![](https://cf03.ickimg.com/bbsimages/201907/b8f7905164be8a4b7c9dd83276e0f770.png) 可以看到,2812芯片对着时序有着较为严格的需要,所以对于0码和1码,我们需要严格控制单片机延时的时间。并且这款芯片的时序大概都在纳秒级的延时,所以对于单片机的要求还是比较高的,我采用的是增强型的51单片机,速度上足够完成纳秒级的延时。 下面看到的数据的输入方法,可以看到每个数据包都是24bit长,也就是3个字节,发送完第一个24bit数据包之后就是接着发送第二个,可以看到在D2线上,第一个24bit数据包自动被忽略了,这是由于WS2812的转发机制,在其接受到第一个完整的24bit数据包之后,再接受到的数据包他会自动将其发送给下一个灯珠,这就是为什么可以一根线控制所有LED灯的秘密。并且WS2812芯片还有锁存的功能,也就是说送一次数据后,在下一回改变颜色之前都不需要再送数据了,内部的锁存电路会自动记住当前的颜色值,并控制灯珠一直保持着色彩。 ![](https://cf03.ickimg.com/bbsimages/201907/d59d2d0bbfa17d81340da0544aedc6ea.png) 对于每一个24bit数据包,其格式如下:每一个字节都表示着颜色的亮度,从高位到低位分别是绿色(G),红色(R),蓝色(B),控制这三个颜色的亮度,我们就可以得到千变万化的色彩。 ![](https://cf03.ickimg.com/bbsimages/201907/10b178ebbc31275a8f7d8a6ccbe458ed.png) 了解到了数据包的格式,数据手册里面还给了一张应用电路的图片,很好的说明了这种单总线LED的连接方法。 ![](https://cf03.ickimg.com/bbsimages/201907/0baa276a532dea6b5ea246565ec1d8d3.png) 看完了数据手册,下面就是对单片机编程,使其可以输出对应的波形了! 首先是对发送0码和1码的程序编写,由于需要用到纳秒级的延时,我使用空语句来进行软件延时,下面是发送0码和1码的代码截图。我这里是使用的STC15系列单片机,使用内部时钟11.0592MHZ,如果有使用相同单片机的朋友请直接参考我的代码,如果你的单片机类型不一样或者时钟频率不一样,最好使用示波器或者逻辑分析仪来得到精确的延时。 ![](https://cf03.ickimg.com/bbsimages/201907/08603d2d3834e38dc06400c2b4721bc3.png) 完成了发送0码和1码之后,接着就是发送一个字节了,核心思路就是每次判断字节高位的值来决定发送0还是1: ![](https://cf03.ickimg.com/bbsimages/201907/04ee041722dd6b811929c1b808e8cc42.png) 经过简单的编程,所有代码就完成了,简单的写了一个程序,让前三个灯亮起,呈红色: ![](https://cf03.ickimg.com/bbsimages/201907/f2783b926f82722948f91f8554c28dc7.jpg) 其实WS2812的编程较为容易,下面就来说一些我的改进地方。 我编写了一个使用串口控制RGB灯的程序,就是我可以在串口上发送数据,实时的控制每个LED灯的颜色,这样会方便后期一些动画效果的控制。我定义了一个数据格式,一个数据包含有5个字节,分别是帧头,LED灯的编号,红色(R)亮度值,绿色(G)亮度值以及蓝色(B)亮度值。例如我想要控制第五个灯变成最亮的白色,我就发送 FFH 05H FFH FFH FFH 就可以了 其思路就是当串口收到帧头之后,就开始读取灯的编号以及各个颜色的亮度值,然后再发送给LED灯珠即可。最后我会附上我的代码,供大家下载。 这些就是单总线LED灯珠的使用方法了,其实编写程序较为简单,主要难点就是大家的时序一定要准确,这样才可以确保灯珠正常的点亮。 ![](https://cf03.ickimg.com/bbsimages/201907/759394b9f2ceffe048f882d6694c2ca5.jpg) ## 下面是代码 ```c #include "intrins.h" u8 RGBALL[96][3]; sbit DAT=P5^4; #define FOSC 11059200UL #define BRT (65536 - FOSC / 9600 / 4) sfr AUXR = 0x8e; sfr T2H = 0xd6; sfr T2L = 0xd7; u8 receiveData; u8 RGB[4]={0,10,100,100}; u8 i=0; u8 OK=0; u8 flag=0; u8 flagg=0; u8 Point; void WS2812_LOW() { DAT=1; _nop_(); DAT=0; _nop_(); _nop_(); _nop_(); } void WS2812_HIGH() { DAT=1; _nop_(); _nop_(); _nop_(); _nop_(); _nop_();//5050µÆÖé¼ÓÕâÒ»ÐУ¬2020²»¼Ó DAT=0; _nop_(); } void WS2812_Byte(u8 WS2812_dat) { u8 WS2812_c; for(WS2812_c=0;WS2812_c<8;WS2812_c++) { if(WS2812_dat&0x80) WS2812_HIGH(); else WS2812_LOW(); WS2812_dat<<=1; } } void WS2812_Dis(u8 R,u8 G,u8 B) { WS2812_Byte(G); WS2812_Byte(R); WS2812_Byte(B); } void WS2812_Init() { u8 WS2812_c; u8 WS2812_cc; DAT=0; for(WS2812_c=0;WS2812_c<96;WS2812_c++) for(WS2812_cc=0;WS2812_cc<3;WS2812_cc++) RGBALL[WS2812_c][WS2812_cc]=0; } void INIT() { P0M1=0; P0M0=0; P1M1=0; P1M0=0; P2M1=0; P2M0=0; P3M1=0; P3M0=0; P4M1=0; P4M0=0; P5M1=0; P5M0=0; } void delay(u16 i) { while(i--); } void main() { u8 main_c; INIT(); SCON = 0x50; T2L = BRT; T2H = BRT >> 8; AUXR = 0x15; ES=1; EA=1; WS2812_Init(); delay(60000); delay(60000); delay(60000); delay(60000); while(1) { if(OK==1) { for(main_c=0;main_c<96;main_c++) WS2812_Dis(RGBALL[main_c][0],RGBALL[main_c][1],RGBALL[main_c][2]); //WS2812_Dis(RGB[1],RGB[2],RGB[3]); OK=0; ES=1; } } } //串口发送数据格式:FF 编号 R G B void UartIsr() interrupt 4 using 1 { receiveData=SBUF; RI=0; if(receiveData==0xff) flag=1; else if(flag==1&&i==0) { Point=receiveData; flagg=1; } if(flagg==1) { RGB[i]=receiveData; i++; } if(i==4) { i=0; flag=0; flagg=0; RGBALL[Point][0]=RGB[1];//存储R值 RGBALL[Point][1]=RGB[2];//存储G值 RGBALL[Point][2]=RGB[3];//存储B值 OK=1; ES=0; } } ```
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
1
)
7566396fd9acf5af
擅长:消费电子 智能硬件
关注
评论
(1)
登录后可评论,请
登录
或
注册
阿紫
214
天前...
这个值得学习
0
回复
发布
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交