一 背景
前段時(shí)間發(fā)現(xiàn)在驅(qū)動(dòng)WS2812B燈條的時(shí)候會(huì)有突然顯示其他顏色的情況,后來(lái)排查發(fā)現(xiàn)是時(shí)序被其他任務(wù)打斷了,在控制時(shí)序的時(shí)候需要做原子性訪問來(lái)保證時(shí)序的正確性。
二 WS2812B數(shù)據(jù)手冊(cè)
2.1 邏輯0和邏輯1
2.2 發(fā)送時(shí)序
綠色數(shù)據(jù)先發(fā),高位在前
三 寫數(shù)據(jù)
3.1 精準(zhǔn)ns和us級(jí)別延時(shí)的實(shí)現(xiàn)
一個(gè)__NOP()的時(shí)間是一個(gè)時(shí)鐘周期,如果主頻設(shè)置的是64MHz,那么一個(gè)時(shí)鐘周期就是1/64000000 = 15.625ns,這里只需要實(shí)現(xiàn)一個(gè)330ns延時(shí),2個(gè)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)//高位先發(fā)
{
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();//關(guān)閉中斷
for(int i=0;i< CONFIG_LED_COUNT;i++)
{
WS2812_Send(green); //發(fā)送當(dāng)前需要亮的燈的顏色
WS2812_Send(red);
WS2812_Send(blue);
}
rt_hw_interrupt_enable(level);//開啟中斷
rt_hw_us_delay(300);//復(fù)位顯示
}
四 總結(jié)
當(dāng)燈的數(shù)量比較多的時(shí)候,就不能用這種延時(shí)方式了,長(zhǎng)時(shí)間的關(guān)閉中斷可能會(huì)引起一些中斷無(wú)法及時(shí)響應(yīng)造成數(shù)據(jù)丟失,在發(fā)現(xiàn)問題的時(shí)候或者調(diào)試新算法的時(shí)候,需要基于數(shù)據(jù)來(lái)分析問題,有了數(shù)據(jù)自然就會(huì)有答案了。
-
驅(qū)動(dòng)器
+關(guān)注
關(guān)注
52文章
8054瀏覽量
145615 -
led燈
+關(guān)注
關(guān)注
22文章
1591瀏覽量
107643 -
GPIO
+關(guān)注
關(guān)注
16文章
1182瀏覽量
51737 -
串口中斷
+關(guān)注
關(guān)注
0文章
64瀏覽量
13824 -
WS2812B
+關(guān)注
關(guān)注
1文章
38瀏覽量
2132
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論