电子说
一 背景
前段时间发现在驱动WS2812B灯条的时候会有突然显示其他颜色的情况,后来排查发现是时序被其他任务打断了,在控制时序的时候需要做原子性访问来保证时序的正确性。
二 WS2812B数据手册
2.1 逻辑0和逻辑1
2.2 发送时序
绿色数据先发,高位在前
三 写数据
3.1 精准ns和us级别延时的实现
一个__NOP()的时间是一个时钟周期,如果主频设置的是64MHz,那么一个时钟周期就是1/64000000 = 15.625ns,这里只需要实现一个330ns延时,2个330ns就是660ns了。
void delay_330ns(void)
{
volatile uint8_t cnt = 21;
while(cnt--)
{
__NOP();
}
}
void delay_660ns(void)
{
volatile uint8_t cnt = 21*2;
while(cnt--)
{
__NOP();
}
}
void ws2812b_write_data(uint8_t data){
for(uint8_t i=0;i< 8;i++)
{
if(data & 0x80)//高位先发
{
GPIOA- >BSRR = GPIO_PIN_8;
delay_660ns();
GPIOA- >BRR = GPIO_PIN_8;
delay_660ns();
}
else
{
GPIOA- >BSRR = GPIO_PIN_8;
delay_330ns();
GPIOA- >BRR = GPIO_PIN_8;
delay_660ns();
}
data< <=1;
}
}
#define CONFIG_LED_COUNT 12
void updata_light(uint8_t green,uint8_t red,uint8_t blue)
{
rt_base_t level = rt_hw_interrupt_disable();//关闭中断
for(int i=0;i< CONFIG_LED_COUNT;i++)
{
WS2812_Send(green); //发送当前需要亮的灯的颜色
WS2812_Send(red);
WS2812_Send(blue);
}
rt_hw_interrupt_enable(level);//开启中断
rt_hw_us_delay(300);//复位显示
}
四 总结
当灯的数量比较多的时候,就不能用这种延时方式了,长时间的关闭中断可能会引起一些中断无法及时响应造成数据丢失,在发现问题的时候或者调试新算法的时候,需要基于数据来分析问题,有了数据自然就会有答案了。
全部0条评论
快来发表一下你的评论吧 !