WS2812C IO口模擬控制

2021-09-30 01:21:24 字數 3243 閱讀 5663

以前,一直很疑惑,那些掛在樹上的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燈條

幾天小朋友到別人家玩,看上了人家的金魚,人家就給了她一條小金魚,有了小金魚,怕它沒氧氣掛掉,買了乙個氧氣幫浦,沒有東西喂它也不行,又買了一包魚料,又因為它太孤單了,又買了幾條小金魚給它做伴,幾條小金魚老是在水桶裡不怎麼好看,又去買了個魚缸,有了魚缸太單調了,也不太好看,想了想加點燈光,後來找出吃灰多...