以前,一直很疑惑,那些掛在樹上的led燈條,是如何實現流水的效果的。燈條是如此的窄,不可能放下很多的訊號線,除非是序列的連線。受限於知識面,一直不太清楚為什麼可以做到,也算是懶,一直沒去查這方面的資料。
直到有一天,突然發現了某個村產的帶鎖存器的5050 led燈珠,才恍然大悟,原來如此。
這段時間,由於要做開關面板,並且面板上需要有背光燈,於是就想起了這個神奇的5050燈珠。。於是就將其畫在了原理圖上。
原理圖很簡單,針對我們使用的ws2812c目前使用5v供電,每顆的vcc腳附近,需要放一顆104電容,因為燈珠內部還有數位電路。另外,就是di,dout的序列資料線。連線在一起即可。
至於前面的電阻電容,只是用來防靜電的一些常用措施。
不同於網路上常用的ws2812b,我們購買的是ws2812c,也得感謝立創,其實為我們這些小公司提供了很大的便利。特別是研發階段的物料購買上。
在軟體上,整體時序如下:
1. 系統上電,ws2812操作口,保持低電平。
2. 開始傳送資料,空閒時,io口為低電平
3. 資料傳送完畢後,維持低電平,超過規格書上定義的reset時間。特別解釋下,只要低電平時間超過規格書上的時間(280us),即可認為是reset,而不需要先拉高,再拉低。
如下是官方提供的整體時序圖。我在網路上搜了很多的bbs和教程,其實大家都很專注在每個bit的實現上,而多數都忽略了整體的時序。也有可能是我的思維方式的問題,我一般喜歡從整體到細節的去掌握乙個東西。了解了整體時序後,在去看位元組組成,再去看位如何實現。
另外,右圖是流程圖。先發資料,後發reset波形。
如下是每24bit的組成。注意,順序不是rgb888,而是grb888。一般我們取顏色的數值,都是rgb順序,所以這裡在**裡實現的時候,會需要做一下移位。另外,需要注意的是,需要高位先發(msb)。
可能是以前的移位暫存器用多了,當發現最近的ws2812鎖存的是第一幀的24bit資料,後面的燈珠依次類推,才發現,這顆燈珠做的其實挺人性化的。這點比以前的移位暫存器好多了。
另外,內部自帶整型,所以掛長條燈帶,也不怕波形畸變了。只能說,雖然是村里出廠的產品,其實考慮了挺多的因素在裡面了。然後,就是確定用什麼樣的波形,來表示bit。波形以及時間引數如下:
用什麼樣的方法去表示bit的波形,網路上的方法有很多。例如pwm,也有用spi。。由於是第一次驅動2812,就先別折騰,我暫時就先用io口模擬來實現吧。
目前選擇的mcu是st新出的stm32g070,主頻設定為64mhz。ws2812的io口連線在pa7上。另外需要注意的是,stm32是3v的電平,ws2812是5v電平,因此這裡需要有一顆常用的電平轉換晶元,我這裡用的是sn74lvc1t45dbvr。電路如下所示:
1. 在gpio口初始化時,將pa7設定為輸出,並且輸出為0.
hal_gpio_writepin(gpioa, gpio_pin_7, gpio_pin_reset);
gpio_initstruct.pin = gpio_pin_5|gpio_pin_6|gpio_pin_7;
gpio_initstruct.mode = gpio_mode_output_pp;//gpio_mode_af_pp;
gpio_initstruct.pull = gpio_nopull;
gpio_initstruct.speed = gpio_speed_freq_very_high;
gpio_initstruct.alternate = gpio_af0_spi1;
hal_gpio_init(gpioa, &gpio_initstruct);
2.定義儲存顏色的緩衝區,我這裡定義了兩個陣列。乙個是儲存原始rgb顏色的陣列,另外乙個是將rgb拆分成grb的陣列。另外,我的板子上總共有8顆2812,因此定義如下:
#define led_count 8
unsigned long rgbbuffer[led_count];
unsigned char grbbuffer[led_count*3];
void ws2812_initial_io(void) //乙個初始化函式:
ws2812_set_led_color(0, 0);
}
//送入的顏色是rgb,所以內部需要轉換一下,index為第幾個燈,rgb是顏色引數
void ws2812_set_led_color(unsigned char index, unsigned long rgb)
gpioa->moder &= 0xffff3fff; //normal gpio
gpioa->moder |= 0x00004000;
unsigned char i;
unsigned char j = 0;
unsigned char dat = 0;
for(j = 0; j < 3*led_count; j++)
else
dat = dat << 1;}}
hal_delay(1); //等待復位結束
}
主函式呼叫方法如下:
ws2812_initial_io();//熄滅所有燈
ws2812_set_led_color(0, 0x0f0000); //第一盞為紅燈,較暗
ws2812_set_led_color(1, 0xf00000); //第二盞為紅燈,較亮
ws2812_set_led_color(2, 0x00ff00); //第三盞為綠燈,全亮
ws2812_set_led_color(3, 0x0000ff); //第四盞為藍燈,全亮
ws2812_set_led_color(4, 0x00ffff); //第五盞為藍白燈,全亮
從以上的**裡,也可以看出來,燈珠的亮度,是可調的,通過調整送入的數值來調整。 RGB三色燈珠WS2812B WS2815B
ws2812b ws2815b均為rgb三色燈珠,ws2815b是ws2812b的公升級版,區別在於兩點,首先是供電電壓由5v變為了12v供電,有效的降低了整個畫素點的工作電流,降低線路板壓降,最大限度保證畫素點在很遠距離傳輸時達到良好的混光一致性。其次是額外增加了一路訊號線,在單個畫素點損壞的情況...
STM32F103C8T6驅動WS2812b燈條
幾天小朋友到別人家玩,看上了人家的金魚,人家就給了她一條小金魚,有了小金魚,怕它沒氧氣掛掉,買了乙個氧氣幫浦,沒有東西喂它也不行,又買了一包魚料,又因為它太孤單了,又買了幾條小金魚給它做伴,幾條小金魚老是在水桶裡不怎麼好看,又去買了個魚缸,有了魚缸太單調了,也不太好看,想了想加點燈光,後來找出吃灰多...