一、简介

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个灯产生随机的颜色
#endif


Ws2812.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)
{
	// 灯的实际写入颜色是GRB
	RGB_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(); 
}
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐