简介:WS2812B 是一款RGB LED驱动集成电路,常用于LED灯带、装饰灯和数字屏幕等。它包含了控制芯片、红、绿、蓝三种不同颜色的LED以及一个电源引脚。WS2812B 的最大特点是其数字信号控制方式,只需通过单根总线即可控制多个WS2812B LED。WS2812B的通信协议使用的是时间间隔调制(Time-Division Multiplexing, TDM)的方法,即为每一个数据位(bit)分配一个固定的时间,通过高低电平的变化来表示不同的数据。例如,当数据位为1时,投射出的波形为低电平持续 0.35us 后切换到高电平,再持续 0.8us,当数据位为0时,投射出的波形为低电平持续 0.8us 后切换到高电平,再持续 0.45us。通过合理的时间间隔控制,可以让WS2812B正确地解析和显示码流数据,它相较于其他LED驱动芯片的优点在于内部集成控制器、单根总线多个LED控制、高亮度丰富颜色显示和多种灯光效果实现,然而,它的缺点是对驱动电压范围的要求较严格、功率消耗较大,需要注意散热和电源供应,并且对通信协议有一定了解要求。
中文数据手册:点我点我
大家好,最近楼楼研究了如何用小安派驱动ws2812这个灯珠,不得不说一下,点灯是楼楼的众多爱好之一,在楼楼的不懈努力之下,终于使用小安派的io点亮了灯珠,分享出来供大家参考
实物展示:
· 显示图片(有没有很眼熟/滑稽)
· 显示文字(小安派yyds/超级大声)
· 一些灯效:
相信大家对于点灯这件事应该已经轻车熟路了,闭着眼都会,楼楼也不啰嗦啦,直接上代码!
代码调用流程: · 初始化: WS2812_init(uint8_t pin, int num_leds, uint8_t brightness, uint8_t mode) ; // 引脚号,灯珠数,亮度,发送顺序(1= rgb,2 = gbr) · 设置颜色: setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b); // 第几颗灯珠,rgb颜色 · 刷新点亮: pixel_show(); 这三步完成烧录后不出意外就可以点亮灯珠
代码:
ws2812.h,新建一个ws2812.h的文件把代码复制进去就可以啦 - /*WS2812RGB彩灯驱动*/
- #ifndef _WS2812_H_
- #define _WS2812_H_
- #include "bflb_mtimer.h"
- #include "bflb_gpio.h"
- typedef union {
- struct {
- uint8_t g;
- uint8_t r;
- uint8_t b;
- } simple;
- uint8_t grb[3];
- } color_t;
- typedef struct _rgb_strip_t {
- int pin_num;
- int num_leds;
- color_t *leds;
- } rgb_strip_t;
- rgb_strip_t strip;
- struct bflb_device_s *gpio;
- uint8_t _pin,_brightness,_mode;
- // 设置亮度.
- void setBrightness(uint8_t brg) {
- _brightness = brg;
- }
- // 引脚初始化.
- /**
- * @brief
- *
- * @param pin 引脚号
- * @param num_leds 灯珠数量
- * @param brightness 亮度
- * @param mode rgb还是gbr顺序发送,1是RGB,2是GBR
- */
- void WS2812_init(uint8_t pin, int num_leds, uint8_t brightness, uint8_t mode) {
- if(mode==1)_mode=1;
- else if (mode == 2)_mode=2;
- else return;
- _pin = pin;
- strip.num_leds = num_leds;
- strip.pin_num = _pin;
- _brightness = brightness;
- strip.leds = (color_t*)malloc(sizeof(color_t) * num_leds);
- for (int i = 0; i < num_leds; i++) {
- strip.leds[i].simple.g = 0;
- strip.leds[i].simple.r = 0;
- strip.leds[i].simple.b = 0;
- }
- gpio = bflb_device_get_by_name("gpio");
- bflb_gpio_init(gpio, pin, GPIO_OUTPUT|GPIO_FLOAT);
- // bflb_gpio_reset(gpio, pin);
-
-
- }
- // RGB发送1码.
- void sendOne(uint8_t GPIO_Pin) {
- bflb_gpio_set(gpio, _pin);
- //延时850ns
- for (volatile int i = 0; i < 30; i++);
- bflb_gpio_reset(gpio, _pin);
- //延时400ns
- for (volatile int i = 0; i < 20; i++);
- }
- // RGB发送0码.
- void sendZero(uint8_t GPIO_Pin) {
- bflb_gpio_set(gpio, _pin);
- //延时400ns
- for (volatile int i = 0; i < 20; i++);
- bflb_gpio_reset(gpio, _pin);
- //延时850ns
- for (volatile int i = 0; i < 30; i++);
- }
- // RGB发送数据.
- void sendRGB(uint8_t pin, uint8_t red, uint8_t green, uint8_t blue) {
- for (uint8_t i = 0; i < 8; i++) {
- if (green & 0x80) {
- sendOne(pin);
- } else {
- sendZero(pin);
- }
- green <<= 1;
- }
- for (uint8_t i = 0; i < 8; i++) {
- if (red & 0x80) {
- sendOne(pin);
- } else {
- sendZero(pin);
- }
- red <<= 1;
- }
- for (uint8_t i = 0; i < 8; i++) {
- if (blue & 0x80) {
- sendOne(pin);
- } else {
- sendZero(pin);
- }
- blue <<= 1;
- }
- }
- // 设置RGB值,如果需要点亮必须调用pixel_show()
- void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
- if (n >= strip.num_leds) {
- return;
- }
- strip.leds[n].simple.r = r;
- strip.leds[n].simple.g = g;
- strip.leds[n].simple.b = b;
- }
- // 刷新RGB.
- void pixel_show(void) {
-
- for(int i=0;i<2;i++){
- for (int i = 0; i < strip.num_leds; i++) {
- color_t pixel = strip.leds[i];
- uint8_t r = pixel.simple.r;
- uint8_t g = pixel.simple.g;
- uint8_t b = pixel.simple.b;
- // 根据亮度调整RGB值
- r = (r * _brightness) >> 8;
- g = (g * _brightness) >> 8;
- b = (b * _brightness) >> 8;
- if(_mode==1)sendRGB(strip.pin_num, r, g, b);
- else sendRGB(strip.pin_num, g, r, b);
- }
- // 延时50us用于刷新数据
- bflb_mtimer_delay_us(50);
- }
- }
- //全部写入一种颜色
- void Pixel_set_all_color(uint8_t red, uint8_t green, uint8_t blue)
- {
- for (int i = 0; i < strip.num_leds; i++)
- {
- strip.leds[i].simple.g = green;
- strip.leds[i].simple.r = red;
- strip.leds[i].simple.b = blue;
- }
- }
- //关闭所有
- void pixel_clear()
- {
- for (int i = 0; i < strip.num_leds; i++)
- {
- strip.leds[i].simple.g = 0;
- strip.leds[i].simple.r = 0;
- strip.leds[i].simple.b = 0;
- }
- pixel_show();
- }
- //=============
- uint32_t color(uint8_t r, uint8_t g, uint8_t b) {
- return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
- }
- // 颜色转换
- uint32_t wheel(uint8_t WheelPos)
- {
- WheelPos = 255 - WheelPos;
- if(WheelPos < 85) {
- return color(255 - WheelPos * 3, 0, WheelPos * 3);
- }
- if(WheelPos < 170) {
- WheelPos -= 85;
- return color(0, WheelPos * 3, 255 - WheelPos * 3);
- }
- WheelPos -= 170;
- return color(WheelPos * 3, 255 - WheelPos * 3, 0);
- }
- // RGB写入32位颜色值
- uint8_t pixel_set_color(uint16_t index, uint32_t col)
- {
- uint8_t r = (uint8_t)(col >> 16);
- uint8_t g = (uint8_t)(col >> 8);
- uint8_t b = (uint8_t)col;
- if (index < strip.num_leds)
- {
- strip.leds[index].simple.r = r;
- strip.leds[index].simple.g = g;
- strip.leds[index].simple.b = b;
- }
- else{
- return 1;
- }
- return 0;
- }
- // 彩虹循环
- void pixel_rainbow(uint8_t tim) {
- uint16_t i, j;
- for(j=0; j<256; j++) {
- for(i=0; i<strip.num_leds; i++) {
- pixel_set_color(i, wheel((i+j) & 255));
- }
- pixel_show();
- bflb_mtimer_delay_ms(tim);
- }
- }
- // 流光溢彩
- void pixel_rainbowCycle(uint8_t tim) {
- uint16_t i, j;
- for(j=0; j<256*5; j++) {
- for(i=0; i< strip.num_leds; i++) {
- pixel_set_color(i, wheel(((i * 256 / strip.num_leds) + j) & 255));
- }
- pixel_show();
- bflb_mtimer_delay_ms(tim);
- }
- }
- //=====单色单灯流水
- void demo_0(uint16_t R,uint8_t G,uint8_t B,uint8_t spd)
- {
-
- for(int b=0; b<3; b++) {
- pixel_clear();
- for(int c=b; c<strip.num_leds; c += 3) {
- setPixelColor(c, R, G, B);
- }
- pixel_show();
- bflb_mtimer_delay_ms(spd);
- }
- }
- //====多彩单灯流水
- void demo_1(uint16_t spd)
- {
- for(int b=0; b<3; b++) {
- pixel_clear();
- for(int c=b; c<strip.num_leds; c += 3) {
- uint8_t r =rand() % 256;
- uint8_t g =rand() % 256;
- uint8_t b =rand() % 256;
- setPixelColor(c, r, g, b);
- }
- pixel_show();
- bflb_mtimer_delay_ms(spd);
- }
- }
- //=====单色扩散===
- void demo_2(uint16_t spd){
- uint8_t r = rand() % 256;
- uint8_t g = rand() % 256;
- uint8_t b =rand() % 256;
- uint8_t x0 = strip.num_leds/2-1;
- uint8_t x1 = strip.num_leds/2+1;
- setPixelColor(strip.num_leds/2,r,g,b);
- for(uint8_t i=0;i<strip.num_leds/2+1;i++){
- setPixelColor(x0,r,g,b);
- setPixelColor(x1,r,g,b);
- pixel_show();
- bflb_mtimer_delay_ms(spd);
- x0--;
- x1++;
- }
- }
- // 13x14点阵字
- void showtext(uint8_t (*letter)[13]) {
- for (int y = 0; y < 14; y++) {
- for (int x = 0; x < 13; x++) {
- if (letter[y][x]) {
- setPixelColor(y * 13 + x, 255, 255, 255);
- } else {
- setPixelColor(y * 13 + x, 0, 0, 0);
- }
- }
- }
- pixel_show();
- }
- #endif
复制代码
main.c文件 - #include "WS2812.h"
- #include "board.h"
- float data;
- int main(void)
- {
- board_init();
- WS2812_init(24, 182, 5,2); // 引脚号,灯珠数,亮度,发送顺序(rgb,gbr)
- bflb_mtimer_delay_ms(100);
- while (1) {
-
- pixel_rainbow(60); //灯效
- // pixel_rainbowCycle(60);
- // demo_2(60);
- bflb_mtimer_delay_ms(1000);
- }
- }
复制代码
楼楼在代码中添加了一些注释,关于灯效的话,大家可以自己研究,楼楼承认楼楼是个小菜鸟,很不专业,如果代码哪里有问题大家可以自行修改!
|
|