rgb珠子的控制方法(按钮控制rgb三色灯)
APA102彩色珠子的使用方法
近两年来,在城市的点亮工程中,可以看到一些彩色灯柱,颜色可变,可以用单一的颜色来显示,可以从上到下或从下到上看到各种渐变,这是APA102的典型应用场景。
在proteus中,发现该元件的模拟也增加了,但是在使用中发现APA102的手册对使用方法不太详细。百度资料的话,在国内介绍这个珠子的资料也很少。这里简单介绍一下APA102的使用方法。
图1ATA102的proteus库的外形
1.硬件概要
APA102是SPI接口的真彩led灯珠、rgb彩色控制、带驱动、可级联、具有256灰度控制和32灰度亮度控制的非常容易使用的彩色灯,led可以用于灯、大型led屏幕以及led看板。
工业级设计,5V供电,单个珠消耗功率0.2瓦,最大不超过1W。
纵横5x5x1.4mm。
图2引脚图
如各个珠的引脚定义如图2所示,除了电源和地脚,DI、CI销分数是数据输入和时钟输入,分别连接到控制器的MOSI和SCK、将DO和CO级联、连接下一珠DI和CI。在使用SPI进行控制的情况下,使用mode0将时钟线空闲周期设为低电平,进行上升边缘采样。
图3SPI模式
2.软件控制方法
图4控制协议
如APA102的软件控制方法如图4所示,除了开头起始帧、最后结尾帧,中间是各led的控制帧。
起始帧的格式是固定的,连续的32比特的0,即连续发送4个16进制。如图5所示。
图5起始帧
结束帧也发送特定长度的0,但是结束帧的长度不固定,公式计算式如下。
例如,如果控制256个珠子,则255×在8/16=128处,需要在末尾发送128bit的0,即16个0x00。在实际使用中测试中,不足8个的情况下,如果不发送4个0x00,则不影响下一个控制,8个以上的情况下,不进行测试。
图6led帧
起始帧和结束帧的中间是led的颜色帧,各led需要一个颜色帧数据,多个led的中间需要发送几个颜色帧。在单一led的控制帧格式如图6中表示。为了控制一个led,需要4字节的数据,第一个字节是亮度信息,第五个比特用于32级的亮度控制。接下来的3个字节是蓝色、绿色和红色的颜色分量控制,每个led灯珠需要4个字节的控制信息。
3.样品代码
使用stm32,以引脚模拟方式进行SPI通信,使用proteus模拟,使用外置库开发代码,样本代码如下。
图7proteus电路连接
样本代码:颜色定义
/*红绿色黑橙色青黄色紫白色*/
u8 color84 = {{255,220,20,60},{255,0,100,0},{255,0,0,0},
{255,0,140,255},{255,255,0,0},{255,0,255,255}, {255,148,0,211},{255,255,255,255}};
/**APA102 DIsplay color**/
#define RED 0x00
#define GREEN 0x01
#define BLACK 0x02
#define ORANGE 0x03
#define BLUE 0x04
#define YELLOW 0x05
#define ZISE 0x06
#define WHITE 0x07
#define Fcolor 0x08
样本代码:APA102显示
/**APA102c DIsplay color defined in color**/
void APADIS(u8 incolor)
{
switch(incolor){
case RED:
SPI_SendByte(0x00);//APA启动,写4个0
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
for(int i=0;ilt;8;i++)
{
SPI_SendByte(0xff);
SPI_SendByte(60);
SPI_SendByte(20);
SPI_SendByte(220);
}
SPI_SendByte(0x00);//停止
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
break;
case GREEN:
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
for(int i=0;ilt;8;i++)
{
SPI_SendByte(0xff);
SPI_SendByte(00);
SPI_SendByte(100);
SPI_SendByte(00);
}
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
break;
case BLACK:
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
for(int i=0;ilt;8;i++)
{
SPI_SendByte(0xff);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
}
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
break;
case ORANGE:
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
for(int i=0;ilt;8;i++)
{
SPI_SendByte(0xff);
SPI_SendByte(00);
SPI_SendByte(140);
SPI_SendByte(255);
}
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
break;
case BLUE:
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
for(int i=0;ilt;8;i++)
{
SPI_SendByte(0xff);
SPI_SendByte(255);
SPI_SendByte(00);
SPI_SendByte(00);
}
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
break;
case YELLOW:
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
for(int i=0;ilt;8;i++)
{
SPI_SendByte(0xff);
SPI_SendByte(00);
SPI_SendByte(255);
SPI_SendByte(255);
}
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
break;
case ZISE:
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
for(int i=0;ilt;8;i++)
{
SPI_SendByte(0xff);
SPI_SendByte(211);
SPI_SendByte(00);
SPI_SendByte(148);
}
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
break;
case WHITE:
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
for(int i=0;ilt;8;i++)
{
SPI_SendByte(0xff);
SPI_SendByte(255);
SPI_SendByte(255);
SPI_SendByte(255);
}
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
break;
case Fcolor:
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
for(int i=0;ilt;8;i++)
for(int j=0;jlt;4;j++)
SPI_SendByte(colorij);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
break;
default:
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
for(int i=0;ilt;8;i++)
for(int j=0;jlt;4;j++)
SPI_SendByte(colorij);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
break;
}
}
样本代码:SPI节
void sSPI2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //ONGPIOD端口
/****SCLKMOSI输出**/
GPIO_InitStructure.GPIO_Pin = SPI_MOSI_Pin|SPI_SCLK_Pin|SPI_SNSS_Pin; //选择低端口2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_pp; //排除力
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M时钟速度
GPIO_Init(SPI_DIFN_GRP, GPIO_InitStructure); //GPIO构成函数
/*MISO输入**/
GPIO_InitStructure.GPIO_Pin = SPI_MISO_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(SPI_DIFN_GRP, GPIO_InitStructure);
}
u8 SPI_SendByte(u8 dt)
{
u8 temp=0,i;
SCLK=0;
for(i=8;igt;0;i–)
{
if(dt0x80)
MOSI=1;
else
MOSI=0;
dtlt;lt;=1;
SCLK=1;
Delay_us(5);
templt;lt;=1;
if(MISO)
temp++;
SCLK=0;
Delay_us(5);
}
SCLK=0;
return temp;
}
u8 SPI_RecvByte(void)/数据接收函数,容易调用
{
u8 SPI_bValue;
for (u8 no=0;nolt;8;no++)
{
SCLK=1;
SPI_bValue=(SPI_bValue lt;lt;1);
Delay_us(5);
SCLK=0;
Delay_us(5);
if(MISO ==1)
SPI_bValue|=0x01;
else
SPI_bValue=~0x01;
}
return SPI_bValue;
}