目录
概要
本工程就是利用了stc8g的1t单片机的高速特性,进行模拟ws2812的协议从而达到控制其点亮的目的,附带详细代码!
stc8g1k08单片机点亮ws2812点阵
技术名词解释
-
1t单片机
1t可以说是相对传统51单片机来说的,理论上比传统51单片机快12倍。并且该型号频率可以达到33mhz。如果以普通的51单片机来类比,当传统51单片机晶振为12mhz时,一条_nop_();指令的时间为1us,而stc8g就是1/12us,约等于0.083us。
-
ws2812
WS2812B-V5是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED灯珠相同, 每个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路,还包含有高精度的 内部振荡器和可编程定电流控制部分,有效保证了像素点光的颜色高度一致。 数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过 来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放 大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。像素点采用 自动整形转发技术,使得该像素点的级联个数不受信号传送的限制,仅受限信号传输速度要求。
-
ws2812详细数据协议
WS2812通过rgb三种颜色来产生理论上255x255x255种颜色,其通信方式如下所示:
所以我们只要模拟出上图的时序就能控制ws2812了,但要注意他的数据顺序是G->R->B
为了更好模拟准确的时序,我们在下载时把内部时钟设置为24mhz,这样一条_nop_();指令的时间为1/24us约等于 0.0417,三条就刚好约为125ns。
详细过程见下面的详细代码!
详细代码
-
main.c
#include <STC8G.H>
#include "WS2812.h"
#include "Delay.h"
void main(void)
{
P5M0 = 0xff; // 将P5口配置为推挽输出
P5M1 = 0x00;
P55=0;//初始P55为低电平
while(1)
{
WS2812_SetSerious(255,0,0,64);//点亮64个灯为红色
Delay(1000); //延时1s
WS2812_SetSerious(0,255,0,64);//点亮64个灯为绿色
Delay(1000); //延时1s
WS2812_SetSerious(0,0,255,64);//点亮64个灯为蓝色
Delay(1000); //延时1s
}
}
-
ws2812.c
#include <STC8G.H>
#include<intrins.h>
/**
* @brief 设置单个灯珠颜色
* @param red 红色的程度 范围0~255
* @param green 绿色的程度 范围0~255
* @param blue 蓝色的程度 范围0~255
* @retval 无
*/
void WS2812_SetSingle(unsigned char red,unsigned char green,unsigned char blue)
{
unsigned char i,j;
for(i=0,j=0x80;i<8;i++)
{
if((green & j)==0)
{
P55=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
P55=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
}
else
{
P55=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
P55=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
}
j=j>>1;
}
for(i=0,j=0x80;i<8;i++)
{
if((red & j)==0)
{
P55=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
P55=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
}
else
{
P55=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
P55=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
}
j=j>>1;
}
for(i=0,j=0x80;i<8;i++)
{
if((blue & j)==0)
{
P55=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
P55=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
}
else
{
P55=1;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
P55=0;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
}
j=j>>1;
}
}
/**
* @brief 设置多个灯珠颜色
* @param red 红色的程度 范围0~255
* @param green 绿色的程度 范围0~255
* @param blue 蓝色的程度 范围0~255
* @param num 灯珠数量 范围0~255
* @retval 无
*/
void WS2812_SetSerious(unsigned char red,unsigned char green,unsigned char blue,unsigned char num)
{
unsigned char i;
for(i=0;i<num;i++)
{
WS2812_SetSingle(red,green,blue);
}
}
-
Delay.c
void Delay(unsigned int xms) // 24mhz
{
unsigned char i,j;
while(xms)
{
i = 32;
j = 40;
do
{
while(--j);
}
while(--i);
xms--;
}
}
-
ws2812.h
#ifndef __WS2812_H__
#define __WS2812_H__
void WS2812_SetSingle(unsigned char red,unsigned char green,unsigned char blue);
void WS2812_SetSerious(unsigned char red,unsigned char green,unsigned char blue,unsigned char num);
#endif
-
Delay.h
#ifndef __DELAY_H__
#define __DELAY_H__
void Delay(unsigned int xms);
#endif
小结
本工程使用STC8G1K08点亮了ws2812点阵,使用的方法肯定还有不足之处,欢迎交流指正!