驱动WS2812B灯条时显示其他颜色咋办?

电子说

1.2w人已加入

描述

一 背景

前段时间发现在驱动WS2812B灯条的时候会有突然显示其他颜色的情况,后来排查发现是时序被其他任务打断了,在控制时序的时候需要做原子性访问来保证时序的正确性。

二 WS2812B数据手册

2.1 逻辑0和逻辑1

WS2812B

2.2 发送时序

WS2812B

绿色数据先发,高位在前

WS2812B

三 写数据

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);//复位显示
}

四 总结

当灯的数量比较多的时候,就不能用这种延时方式了,长时间的关闭中断可能会引起一些中断无法及时响应造成数据丢失,在发现问题的时候或者调试新算法的时候,需要基于数据来分析问题,有了数据自然就会有答案了。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
评论(0)
发评论
jf_23937618 04-23
0 回复 举报
电压的问题? 收起回复

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分