ws2812B+单片机驱动

news/2025/3/26 15:08:49/

文章目录

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

效果

呼吸

请添加图片描述

流水

请添加图片描述

跑马

请添加图片描述

随机灯带

请添加图片描述

WS2812B 驱动

数据协议

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

RES帧单位,低电平时间330us以上
T0L0码,低电平时间750ns~1.6us
T0H0码,高电平时间220ns~420ns
T1H1码,高电平时间750ns~1.6us
T1L0码,低电平时间220ns~420ns

注意一点就行了:比例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

在这里插入图片描述
在这里插入图片描述

文章来源:https://blog.csdn.net/qq_37429313/article/details/121840998
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ppmy.cn/news/205643.html

相关文章

ws和wss的区别

First WS: WebSocket WSS: WebSocket Secure WS协议和WSS协议两个均是WebSocket协议的SCHEM WebSocket协议是html5的一种通信协议&#xff0c;可以使客户端和服务端双向数据传输更加简单快捷&#xff0c;并且在TCP连接进行一次握手后&#xff0c;就可以持久性连接&#xff0c;…

华为认证WLAN高级工程师 HCIP-WLAN V2.0(中文版)预发布通知

2022-09-23 17:12 尊敬的客户&#xff1a; 非常荣幸地通知您&#xff0c;华为认证HCIP-WLAN V2.0&#xff08;中文版&#xff09;预计将于2022年10月31日正式对外发布。为了帮助您做好学习、培训和考试计划&#xff0c;现进行预发布通知&#xff0c;请您关注。 HCIP-WLAN V1.0…

websocket和http2

websocket和http的区别 http: 连接不持久&#xff0c;服务器不能主动推动内容 websocket&#xff1a; 连接持久&#xff0c;服务器可以主动推送内容 细节&#xff1a; websocket数据格式轻量&#xff0c;性能开销小&#xff0c;数据交换时&#xff0c;包头的字节只有2-10字节&…

W801/W800-wifi-socket开发(一)-UDP

这是目录 一、项目概述二、socket-udp官方SDK梳理1、连接路由器2、连接UDP 三、项目设计四、测试 本文使用环境&#xff1a; 主控&#xff1a;W800-KIT (开发板) 兼容&#xff1a;W800 W801 AIR101 开发环境&#xff1a;CDK SDK&#xff1a;W801/W800的SDK(tls库) 我的联盛德问…

CS131 HW3

Homework 3 该作业涵盖了用于全景拼接的 Harris 角点检测器、RANSAC 和 HOG 描述符。 在本次作业中&#xff0c;我们将从多张图像中检测和匹配关键点以构建单个全景图像。这将涉及几个任务&#xff1a; 1.使用 Harris 角点检测器查找关键点。 2.构建一个描述符来描述图像中的…

ws832设置虚拟服务器,华为路由器ws832怎么设置

支持RIP、OSPF、BGP、IS-IS等单播路由协议和IGMP、PIM、MBGP、MSDP等多播路由协议&#xff0c;支持路由策略以及策略路由&#xff0c;那么你知道华为荣耀路由器ws832怎么设置吗?下面是学习啦小编整理的一些关于华为荣耀路由器ws832设置的相关资料&#xff0c;供你参考。 华为荣…

华为ws832虚拟服务器,玩的就是真实力!华为路由WS832实测体验

原标题:玩的就是真实力!华为路由WS832实测体验 现在家里的无线智能设备越来越多,从手机到平板电脑甚至到智能电视都离不开WIFI信号。所以一款优秀的路由器成为每个家庭的必备。虽然各个厂商都纷纷推出自己的路由设备,但是质量参差不齐,最近华为推出了一款家用高端路由器WS…

无线桥接dhcp服务器怎么设置,华为路由器怎么设置桥接(2)

步骤四、副路由器B中设置WDS桥接 点击“家庭网络”——>“WDS网桥”——>“2.4GHz频段”——>勾选“启用”——>点击“扫描”——>在扫描结果中&#xff0c;找到WiFi名称&#xff0c;点击后面的小圆点——>点击“保存”。 副路由器B中启用WDS桥接&#xff0c…