不多说请看注释及源码,有用到或转发的请记住这是缥缈九哥(yuanxihua@21cn.com)原创:
/*******************************************************************************************
WS2812S的标准时序如下:
TH+TL=1.25us±150ns, RES>50us
T0H=0.25us±150ns = 0.10us - 0.40us
T1H=1.00us±150ns = 0.85us - 1.15us
T0L=1.00us±150ns = 0.85us - 1.15us
T1L=0.25us±150ns = 0.10us - 0.40us
占空比取1:3,Bit = 0.290us - 0.350us , T=1.160us - 1.40us
用UART的TXD驱动WS2812,采用3M即0.333US的波特率。
那么起始位+D0D1D2位组合成0111做为WS2812的0码,D3D4D5D6位0001做为WS2812的1码;
或者起始位+D0D1D2位组合成0001做为WS2812的1码,D3D4D5D6位0111做为WS2812的0码;
而且剩下的D7+结束位+2位字间空隙组合成固定的1111为新的空闲位。
那么只要外置74HC04做反相功能,即可符合标准的WS2812的接收的时序要求。
即是T0H=0.333US,T0L=0.999US,T1H=0.999US,T1L=0.333US;
即是TH+TL=1.332us 小于周期1.4US,而且 IDLE=1.332uS 小于RES的50us时间,以上状态会保持下去。
结论:用连续12个字节的UART信号即可传送一个WS2812显示像素24位数据。
*********************************************************************************************/
#include "SWM1800.h"
#include "cmsis_os.h"
#include "string.h"
#include <stdlib.h>
typedef __packed struct
{
uint8_t blue;
uint8_t green;
uint8_t red;
uint8_t white;
}pixel_t;
void UART1Init(void)
{
UART_InitStructure UART_initStruct;
PORT_Init(PORTA, PIN0, FUNMUX_UART1_RXD, 1); //GPIOA.0配置为UART1输入引脚
PORT_Init(PORTA, PIN1, FUNMUX_UART1_TXD, 0); //GPIOA.1配置为UART1输出引脚
UART_initStruct.Baudrate = 3000000; //=clk/16/x BIT = 0.333us
UART_initStruct.TXThreshold = 0; //取值0--7
UART_initStruct.TXThresholdIEn = 0; //当TX FIFO中数据个数 <= TXThreshold时触发中断
UART_initStruct.RXThreshold = 7; //取值0--7
UART_initStruct.RXThresholdIEn = 1; //当RX FIFO中数据个数 >= RXThreshold时触发中断
UART_initStruct.TimeoutTime = 20; //超时时长 = TimeoutTime/(Baudrate/10) 秒
UART_initStruct.TimeoutIEn = 1; //超时中断,超过 TimeoutTime/(Baudrate/10) 秒没有在RX线上接收到数据时触发中断
UART_Init(UART1, &UART_initStruct);
UART_Open(UART1);
}
void Uart1Write(char data)
{
UART_WriteByte(UART1, data);
while(UART_IsTXBusy(UART1));
}
#if 0
void Uart1Test(void)
{
UART1Init();
while(1){Uart1Write(0x55);}
}
void Ws2812Reset(void)
{
GPIO_Init(GPIOA, PIN1, 1, 0, 0, 0); //GPIOA.1配置为输出引脚,推挽输出
GPIO_SetBit(GPIOA, PIN1);
osDelay(1);//延时60us以上
PORT_Init(PORTA, PIN1, FUNMUX_UART1_TXD, 0); //GPIOA.1配置为UART1输出引脚
}
#endif
void Ws2812WriteByte(uint8_t byte)
{
for(uint8_t i=0;i<4;i++)
{
uint8_t data=((byte&0x80)?0x04:0x07)|((byte&0x40)?0x40:0x70)|0x80; // D0-D2:D3-D6:D7
Uart1Write(data);
byte<<=2;
}
}
void Ws2812Pixel(pixel_t *pixel,uint32_t length)
{
osDelay(1);//延时1ms以复位
__disable_irq();
for(uint32_t i=0;i<length;i++)
{
Ws2812WriteByte(pixel[i].green); //绿色
Ws2812WriteByte(pixel[i].red); //红色
Ws2812WriteByte(pixel[i].blue); //蓝色
}
__enable_irq();
}
void Ws2812Test(void)
{
uint32_t i=0,j,color[8],len=8,dly=4;
UART1Init();
while(1)
{
while(i++<255){for(j=0;j<8;j++){color[j]=i<<16;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
while(i--> 1){for(j=0;j<8;j++){color[j]=i<<16;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
while(i++<255){for(j=0;j<8;j++){color[j]=i<< 8;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
while(i--> 1){for(j=0;j<8;j++){color[j]=i<< 8;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
while(i++<255){for(j=0;j<8;j++){color[j]=i<< 0;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
while(i--> 1){for(j=0;j<8;j++){color[j]=i<< 0;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
}
}
全文完毕。
离线
级联的。
离线