1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > ws2812B+单片机驱动

ws2812B+单片机驱动

时间:2023-05-04 20:30:54

相关推荐

ws2812B+单片机驱动

文章目录

效果呼吸流水跑马随机灯带WS2812B 驱动数据协议24bit数据结构程序main.cws.cws.h待做

效果

呼吸

流水

跑马

随机灯带

WS2812B 驱动

数据协议

采用单线归零码,每个像素点(灯),在接受到自己的24bit数据后,将剩下的数据再处理放大后,发出去,也就是每经过一个点,数据少24bit。

注意一点就行了:比例3:1,

比如:

T0L 750ns

T0H 250ns

其对时序要求还是很高的,因此一定要满足要求,不要再数据发的过程中做一些耗时的操作

24bit数据结构

|G7|G6|G5|G4|G3|G2|G1|G0|R7|R6|R5|R4|R3|R2|R1|R0|B7|B6|B5|B4|B3|B2|B1|B0|

高位在前,按照GRB顺序

程序

注意stc15的话,该程序的晶振需设置为24M

main.c

#include <stc15f2k60s2.h>#include <stdio.h>#include "ws.h"#include <INTRINS.H>#define uchar unsigned char#define uint unsigned int#define LEDCNT 50 //灯的数目sbit k1 = P3^0; //按键一 控制模式sbit k2 = P3^1;//按键二 关闭灯光//成员依次为计时最大值,计时数,是否完成计时typedef struct delay{uint max;uint cnt;uchar ok;} t_delay;//灯的切换速度(因为定时器是2ms,所以300*2=600ms,以下同理)t_delay delaytime = {300, 0, 0};//流水灯的速度(可以设置一个变量然后使用按键控制,都是可以的)t_delay liushui_time = {30, 0, 0};//呼吸灯呼吸的速度t_delay huxi_time = {100, 0, 0};//GRB//流水灯流完一次改变颜色code ws_t wsData[] = {{255,0, 0}, {0, 255, 0}, {0, 0, 250}};//跑马灯的设置code ws_t PAOMACODE[] = {{255, 0, 0}, {0, 255, 0}, {0, 0, 255}};unsigned int SEED = 0;//随机数种子//当前按键值,上一次按键值,按键计数uchar key, tmpKey, keyCnt;enum{K_GT,K_AS,K_WA} keyState = K_GT;enum{HUXI,LIUSHUI,PAOMA,SUIJI,XIMIE}gloState = LIUSHUI;//单次获取按键uchar GetKey(){if (k1 == 0)return 1;else if(k2 == 0)return 2;return 0;}//自我设定定时器运行void TimeRun(t_delay *time){if (time->cnt++ < time->max);else{time->cnt = 0;time->ok = 1;}}void Timer1Init(void) // 2毫秒@12.000MHz{AUXR |= 0x40;//定时器时钟1T模式TMOD &= 0x0F;//设置定时器模式TL1 = 0x80;//设置定时初值TH1 = 0x44;//设置定时初值TF1 = 0;//清除TF1标志TR1 = 1;//定时器1开始计时ET1 = 1;}//为了调试用的void UartInit(void){SCON = 0x50;AUXR |= 0x01;AUXR |= 0x04;T2L = 0xE0;T2H = 0xFE;AUXR |= 0x10;ES = 0;}void Timer1Handle() interrupt 3{switch (keyState){case K_GT:tmpKey = GetKey();keyState = K_AS;keyCnt = 0;break;case K_AS:if (keyCnt++ < 10);else if (tmpKey == GetKey()){if (tmpKey != key){key = tmpKey;keyState = K_WA;}elsekeyState = K_GT;}elsekeyState = K_GT;break;}//在定时器中计算一个定时TimeRun(&delaytime);TimeRun(&liushui_time);TimeRun(&huxi_time);}void Liushui(){static uchar i = 0;static uchar color = 0;if(liushui_time.ok == 1){liushui_time.ok = 0;SendLiushui(LEDCNT, i, wsData[color]);i = (i + 1)%LEDCNT;if(i == 0){color = (color + 1)%3;}}}void Paoma(){static uchar i = 0;if(delaytime.ok == 1){delaytime.ok = 0;SendPaoma(LEDCNT, PAOMACODE[i]);i = (i + 1)%3;}}void Suiji(){if(delaytime.ok == 1){delaytime.ok = 0;SendSuiji(LEDCNT);}}void Huxi(){static uchar i = 0;if(huxi_time.ok == 1){huxi_time.ok = 0;SendHuxi(LEDCNT, i);i = (i + 1)%30;}}void main(){Timer1Init();UartInit();EA = 1;while (1){switch(gloState){case LIUSHUI:Liushui();break;case PAOMA:Paoma();break;case SUIJI:Suiji();break;case HUXI:Huxi();break;}if(keyState == K_WA){if(key == 1){if(gloState == XIMIE){gloState = HUXI;}else{gloState = (gloState + 1)%4;}}else if(key == 2)//如果按键二按下,则熄灭全部灯{SendXime(LEDCNT);gloState = XIMIE;}keyState = K_GT;}}}

ws.c

#include <STC15F2K60S2.H>#include <INTRINS.H>#include <stdio.h>#include <stdlib.h>#include "ws.h"sbit LED = P2^4; //灯带的数据输入//呼吸灯的值(这部分可以写一个RGB2HSV转换,这里我直接查找的值)code ws_t HUXICODE[] = {{32,11,227}, {29,10,201},{23,7,165}, {21,7,143}, {17,5,122},{15,5,101},{12,4,81}, {6,2,43}, {3,1,18}, {0,0,0},{31,219,4}, {27,188,3},{23,167,3}, {21,146,3}, {18,125,2},{15,104,2},{12,84,1}, {7,52,1}, {5,33,1}, {0,0,0},{218,100,3}, {188,86,3},{167,77,3}, {149,68,2}, {125,57,2},{104,48,2},{84,38,1}, {63,29,1}, {26,12,0}, {0,0,0}};//每一帧至少的间隙void Delay300us()//@24.000MHz{unsigned char i, j;i = 1;j = 146;do{while (--j);} while (--i);}//发送24个bit数据void WS_SendData(ws_t *_data){uchar i = 0;uchar j = 0;uchar *p = (uchar*)_data;EA = 0;for (i = 0; i < 3; i++){uchar tmpData;tmpData = *(p++);for (j = 0; j < 8; j++){if (((tmpData>>(7-j)) & 0x01) == 0){LED = 1;_nop_();_nop_();_nop_(); LED = 0;_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();}else{LED = 1;_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();LED = 0;_nop_();_nop_();_nop_(); }}}EA = 1;}//流水灯//总个数,哪一个灯亮,亮什么值void SendLiushui(uchar num,uchar whichLight, ws_t _data){uint i = 0;ws_t ximieValue = {0, 0, 0};for(i = 0; i< num+1; i++){//到该亮的地方才亮if((i >= whichLight) && (i <= whichLight + 5)){WS_SendData(&_data);}else{WS_SendData(&ximieValue);}}Delay300us();}//熄灭所有灯void SendXime(uchar num){uint i = 0;ws_t ximieValue = {0, 0, 0};for(i = 0; i< num+1; i++){WS_SendData(&ximieValue);}LED = 0;Delay300us();}//跑马灯void SendPaoma(uchar num, ws_t _data){static uchar start = 0;uint i = 0;ws_t ximieValue = {0, 0, 0};for(i = 0; i< num+1; i++){//一半亮一半不亮if((i%2) == start){WS_SendData(&_data);}else{WS_SendData(&ximieValue);}}start = (start + 1)%2;Delay300us();}void SendSuiji(uchar num){uint i = 0;for(i = 0; i< num+1; i++){//随机颜色ws_t suijiValue = {0,0,0};suijiValue.green = SEED>>8;suijiValue.red = SEED;suijiValue.blue = ~SEED;SEED = SEED + 455;WS_SendData(&suijiValue);}Delay300us();}//根据已经设定的值来亮void SendHuxi(uchar num, uchar lightLevel){uint i = 0;for(i = 0; i< num+1; i++){WS_SendData(&HUXICODE[lightLevel]);}Delay300us();}

ws.h

#ifndef _WS_H#define _WS_H#define uchar unsigned char#define uint unsigned intextern unsigned int SEED;//随机种子typedef struct ws{uchar green;uchar red;uchar blue;}ws_t;void WS_SendData(ws_t* _data);void SendLiushui(uchar num,uchar whichLight, ws_t _data);void SendXime(uchar num);void SendPaoma(uchar num, ws_t _data);unsigned int random(unsigned int xxx);void SendSuiji(uchar num);void SendHuxi(uchar num, uchar lightLevel);#endif

待做

RGB2HSV

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。