文章目录
一、SK6812是什么?
SK6812是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个SMD5050顶面发光LED灯珠相同 ,每个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路,电源稳压电路,内置 恒流电路,高精度RC振荡器,输出驱动采用专利PWM技术,有效保证了像素点内光的颜色高一致性。
1、工作原理
SK6812和WS2812一样,数据协议都是采用单极性归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后 通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。像素点采用自动整形 转发技术,使得该像素点的级联个数不受信号传送的限制,仅仅受限信号传输速度要求。
这时候你肯定会有疑问,什么是单极性归零码?
由上面这张图你就知道单极性归零码是一种编码方式,包含“0”码和“1”码,高电平时间宽度决定了你发送的是“0”码还是“1”码。
2、典型电路
这是规格书上的简单的典型应用电路,实际我们应用的时候还可以在电路上加一个钽电容以及在每一个RGB旁放置一个小电容。
为什么我们要这么做呢?这是因为:
1.总所周知,电解电容具有良好的滤波性能,可以稳定电源电压并减小电源噪声。RGB LED需要比较高精度的电源电压,我们在电路中加入钽电容可以有效地过滤掉电源中的高频噪声,确保RGB LED的电压稳定;
2.在RGB LED的亮度调节过程中,会产生较大的瞬态电流。加入钽电容可以提供充足的电流支撑,使RGB LED的亮度调节更加平稳,减少闪烁和颜色失真等问题。
3.在每一个LED灯珠旁边放置电容的作用是为了进一步稳定LED灯珠的工作电压,并提高LED灯珠的寿命。由于LED灯珠对电压的要求较高,且其内部具有较大的电容负载,因此在LED灯珠旁边加入电容可以减小电源对LED灯珠的影响,提高LED灯珠的工作效率。
3、驱动代码
3.1 初始化代码如下(示例):
DIN输入脚我们配置为推挽输出模式
/*******************************************************************************
* 函数名:RGB_GPIO_Init
* 描述 :RGB引脚配置初始化
* 输入 :void
* 输出 :void
* 调用 :初始化
* 备注 :
*******************************************************************************/
void RGB_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : Pin */
GPIO_InitStruct.Pin = DIN1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(RGB_GPIO_Port, &GPIO_InitStruct);
}
3.2 时序代码如下(示例):
根据时序表,我们写出发送“0”码和发送“1”码
//以下的时间延时基于STM32G0单片机,时间不是特别准确。更换MCU需要自行修改,用示波器确认时间
#define _delay_300ns() \
do{ \
uint8_t delay_300ns_cnt = 0; \
for(delay_300ns_cnt = 0;delay_300ns_cnt < 2;delay_300ns_cnt++) \
{ \
__NOP(); \
} \
}while(0)
#define _delay_1us() \
do{ \
uint8_t delay_1us_cnt = 0; \
for(delay_1us_cnt = 0;delay_1us_cnt < 6;delay_1us_cnt++) \
{ \
__NOP(); \
} \
}while(0)
#define SEND_BIT_VOL(n) \
do{\
if(!n) \
{HAL_GPIO_WritePin(RGB_GPIO_Port,DIN1_Pin,GPIO_PIN_SET);__NOP();LED_DIN1_OFF();_delay_1us();}\
else \
{LED_DIN1_ON();_delay_300ns();LED_DIN1_OFF();_delay_1us();}\
}while(0)```
3.3 写数据代码如下(示例):
/*******************************************************************************
* 函数名:Out8
* 描述 :往对应位置写入8位数据
* 输入 :dat
* 输出 :void
* 调用 :
* 备注 :
*******************************************************************************/
void Out8(uint8_t dat)
{
volatile uint8_t i;
uint8_t tmp;
tmp = dat;
for(i = 0;i < 8;i++)
{
if(tmp & 0x80 )
{
SEND_BIT_VOL(1);
}
else
{
SEND_BIT_VOL(0);
}
tmp <<= 1;
}
}
这里解释下为什么要关总中断,再开启总中断。是因为我在测试呼吸RGB的时候发现如果写入数据量太大,会导致个别灯珠异常,查找问题发现是中断导致的,所以才加了这个。
然后为什么还有个W,是因为我用到的是RGBW灯珠,相比较RGB灯珠,它多了一路白光控制通道,使得在调节亮度和色彩饱和度时更加灵活,并且能够呈现更加自然的白光。
/*******************************************************************************
* 函数名:Out32
* 描述 :往对应位置写入32位数据
* 输入 :clg,clr,clb,clw
* 输出 :void
* 调用 :
* 备注 :R,G,B,W
*******************************************************************************/
void Out32(uint8_t clg,uint8_t clr,uint8_t clb,uint8_t clw )
{
__disable_irq();//关总中断
Out8 ( clg );
Out8 ( clr );
Out8 ( clb );
Out8 ( clw );
__enable_irq();//使能总中断
}
3.4 流水灯代码如下(示例):
如需更改颜色,修改.h文件里面的值即可
//******************** G R B W
#define COLOR_WHILE 0 , 0 , 0, 20
#define COLOR_BLUE 0 , 0 , 20, 0
#define COLOR_RED 0 , 20 , 0, 0
#define COLOR_GREEN 20, 0 , 0, 0
/*******************************************************************************
* 函数名:Running_RGB
* 描述 :流水RGB
* 输入 :void
* 输出 :void
* 调用 :
* 备注 :1蓝
*******************************************************************************/
void Running_RGB(void)
{
uint8_t i;
uint8_t j;
for ( i = 0; i <= MAX_NUM; i++ )
{
for ( j = 0; j < i; j++ )
{
Out32(COLOR_BLUE);//blue
}
LED_DIN1_OFF();
_delay_100us();//复位需要大于80us
if(MAX_NUM == 50)
{
delay_syms(10);
}
else
{
delay_syms(20);
}
}
delay_syms(100);
Close_All_RGB();
}
二、总结
今天介绍了RGB灯珠的的原理和简单应用,有兴趣的可以下载驱动附件参考,附件有多种颜色的流水,呼吸等效果,感谢你的观看,谢谢!