文章目录
- 一、简介
- 二、原理
- 三、硬件介绍
- 四、通信协议
- 五、程序
一、简介
WS2812只需要一根信号线就能控制灯的多种颜色的变化,多个灯可以级联,在30hz的刷新频率下一个信号线能够控制至多500个LED。
二、原理
WS2812B是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED灯珠相同,每个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路,还包含有高精度的内部振荡器和可编程定电流控制部分,有效保证了像素点光的颜色高度一致。
三、硬件介绍
1.内置信号整形电路,任何一个像素点收到信号后经过波形整形再输出,保证线路波形畸变不会累加。
2.内置上电复位和掉电复位电路
3.每个像素点的三基色颜色可实现256级亮度显示,完成16777216中颜色的全真彩显示,扫描频率不低于400hz/s
4.串行级联接口,能通过一根信号线完成数据的接收和接码。
5.数据发送速度可达800kbps(相当于1.25us传输一比特数据)
四、通信协议
数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。像素点采用自动整形转发技术,使得该像素点的级联个数不受信号传送的限制,仅仅受限信号传输速度要求。
数据码的逻辑实现:
文档部分参考这位作者:
https://blog.csdn.net/tangxing1212/article/details/42964417
五、程序
调试延迟的时候可以用小马哥视频的方法
这里给出链接。
https://www.bilibili.com/video/BV1Qs41137dk/?spm_id_from=333.788.videocard.0
Ws2812.h#ifndef WS2812
#define WS2812#define RGB_Port_RCC RCC_APB2Periph_GPIOB //RGB时钟
#define RGB_PIN GPIO_Pin_9 //RGB引脚
#define RGB_PORT GPIOB //RGB端口#define RGBLED PBout(9) //RGB灯// 发送0x000000是关闭灯void RGB_Init(void); // RGB初始化IO管脚
void RGB_ColorSet(uchar red,uchar green,uchar blue); // 设置一个灯的颜色
void RGB_RandomColor(void); // 产生随机数颜色
void RGB_RandomColor4(void); // 4个灯产生随机的颜色
#endifWs2812.c#include "All.h"// RGBLED 管脚初始化
void RGB_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RGB_Port_RCC,ENABLE);//系统时钟使能GPIO_InitStructure.GPIO_Pin = RGB_PIN; //定义管脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//管脚输出模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//管脚的速度GPIO_Init(RGB_PORT,&GPIO_InitStructure); //初始化端口}// 信号0 300ns高电平 900ns低电平
void RGB_Write0(void)
{uchar cnt1=1,cnt2 = 5;RGBLED = 1; // 高电平while(cnt1--) // 300ns__nop();RGBLED = 0;while(cnt2--) // 900ns__nop();
}// 信号1 600ns高电平 600ns低电平
void RGB_Write1(void)
{uchar cnt1=3,cnt2 = 3;RGBLED = 1; // 高电平while(cnt1--) // 600ns__nop();RGBLED = 0;while(cnt2--) // 600ns__nop();
}
// 复位 80us低电平
void RGB_LEDReset()
{RGBLED = 0;delay_us(80);
}// RGB写一个字节
void RGB_WriteByte(uchar dat)
{uchar i;for(i= 0;i<8;i++){dat <<= i;if(dat & 0x80) // 判断最高位{RGB_Write1(); // 写1}else{RGB_Write0(); // 写0}}
}// 设置一个灯的颜色
void RGB_ColorSet(uchar red,uchar green,uchar blue)
{// 灯的实际写入颜色是GRBRGB_WriteByte(green); // 写入绿色RGB_WriteByte(red); // 写入红色RGB_WriteByte(blue); // 写入蓝色
}// 产生一个随机的颜色
void RGB_RandomColor(void)
{uchar red,green,blue; // srand((int)time(0)); // 设置随机种子red = rand() % 255; //产生随机数在一个字节的范围内green = rand() % 255;blue = rand() % 255;RGB_ColorSet(red,green,blue); // 合成颜色
}/* 4个灯各自产生随机的颜色*/
void RGB_RandomColor4(void)
{RGB_RandomColor(); // 产生随机颜色RGB_RandomColor(); RGB_RandomColor(); RGB_RandomColor();
}