【有趣的全彩LED | 编程】用STM32 HAL库让WS2812B为你所动

一、效果展示

 

 

观看演示效果:https://www.bilibili.com/video/BV1dv411Y7x3

 

使用STM32 HAL库编程 PWM+DMA控制输出,CubeMX生成初始工程

实现全彩音乐灯

WS2812B全彩流水灯效果展示及理论详细讲解

WS2812B的主要用途是在路边的氛围灯,我们在一些公园里看到五彩斑斓闪烁的灯基本都是WS2812为基础的灯带

 

另外我们还可以通过纯软件延时的方式来控制数据发送,这可以方便程序移植

 

 

二、 基础认识

(一)  小理论

WS2812B是一种智能控制LED光源,将控制电路和RGB芯片集成在一个5050个组件的封装中。内部包括智能数字端口数据锁存和信号整形放大驱动电路。还包括精密的内部振荡器和电压可编程恒流控制部分,有效保证像素点的光色高度一致。

数据传输协议采用单NZR通信模式。像素上电复位后,DIN端口从控制器接收数据,第一个像素采集初始24位数据,然后发送给内部数据锁存器,其他经过内部信号整形放大电路整形后的数据通过DO端口发送给下一个级联像素。每传输一个像素后,信号减少24位。像素采用自整形传输技术,使得像素级联数不受信号传输的限制,只取决于信号传输的速度。

复位时间>280us,中断时不会误复位,支持低频率,价格低廉的MCU。刷新频率更新至2KHz,无闪烁,提高了出色的显示效果。

特性:

l  控制电路和LED共用唯一的电源。

l  控制电路和RGB芯片集成在一个5050个元件的封装中,形成一个完整的可寻址电路

l  像素内置信号整形电路,波形整形到下一个驱动器后,保证波形失真不累积。

l  内置电子复位电路和失电复位电路。

l  每个像素的三原色都可以实现256亮度的显示,完成16777216色的全彩显示,并且扫描频率为2KHz。

l  级联端口通过单线传输信号。

l  任意两点距离不超过5m传输信号无需任何增加电路。

l  刷新率为30fps时,级联个数不小于1024像素。

l  以800Kbps的速度发送数据。

l  灯的颜色高度一致,性价比高不需要外部电子元件,甚至不需要电容。

(二)   样式汇总

1

灯板矩阵

灯带

灯板

三、硬件简介

灯带参数:WS2812B灯条:30珠每米9w,60珠每米18w,144珠每米43W,电压:(直流)DC5V

也就是每个灯珠全亮的功耗约为0.3W

 

l  供电:5V

l  每个灯珠全亮的功率:0.3W

l  每个灯珠全亮的电流:0.6mA

 

每个芯片有四个引脚

级联接线方式

上一个芯片的DO接到下一个芯片的DI

 

 

四、编程思路

SW2812是一个RGB芯片,所以它有红、绿、蓝三种颜色,每个颜色有对应8位,因为我们通常一个像素点就是用RGB三色来表示的,比如经常见到的#FFFFFF,其就是表示R(红色)的值为255,G(绿色)的值为255,B(蓝色)的值为255,#FFFFFFF是白色。所以一个SW2812由3个U8,也就是3*8=24位。要确定一个SW28122芯片的颜色就需要发送24位的数据。

 

级联数据发送

l  第一屏数据缓存

u  第一个24位有第一个模块接收并缓存

u  第二个24位会被第一个模块转发到第二个模块上,并缓存

u  第三个24位会被第一和第二个转发到低三个模块上,并缓存

u  第四个24位……

u  低N个24位……

l  复位信号,也就是将缓存数据真实的体现到显示上

l  第二屏数据缓存

u  第一个24位有第一个模块接收并缓存

u  第二个24位会被第一个模块转发到第二个模块上,并缓存

u  第三个24位会被第一和第二个转发到低三个模块上,并缓存

u  第四个24位……

u  低N个24位……

l  复位信号,也就是将缓存数据真实的体现到显示上

l  ……

每个24位数据表示的意义

数据按GRB顺序传输,先传输高位

数据位

 

 

五、 程序设计

手册上介绍数据发送速度是:800Kbps

所以每个数据位的时间是:1/800000=0.00000125s=1.25us

 

这1.25us可以表示高位或低位,24个1.25us就是一个灯的颜色,发完一个灯的颜色后需要发送大于280us的低电平让数据从锁存器表现在灯上。

 

数位位0:

周期1/3的高电平,1.25*(1/3)us

周期2/3的低电平,1.25*(2/3)us

 

数位位1:

周期2/3的高电平,1.25*(1/3)us

周期1/3的低电平,1.25*(1/3)us

六、控制方式1(循环数据发送)

一位一位数据循环发送,因为WS2812对时序要求很高,所以单片机要注意延时时间和IO的电平翻转时间。

 

在单片机没有高级外设的情况下就得用这个了

 

编程要点:

l  延时时间要支持最小的1.25*(1/3)us

l  IO电平翻转尽可能的快,进入去操作寄存器改变IO电平,减少延时时间,在STM32里要把GPIO的时钟设置高些

l  程序关闭中断,程序的其它中断可能会引起发送数据时序错乱

l  其缺点就是占用主程序,各种延时消耗很大的CPU资源

七、 控制方式2(HAL库 PWM+DMA)

PWM

PWM即脉冲宽度调制,是一种模拟控制方式,通常用于LED的亮度调节。

详细参考:https://www.cnblogs.com/dongxiaodong/p/14351398.html

 

DMA

直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无需CPU干涉,数据可以通过DMA快速移动,这样可以大大节省CPU的资源用来做其它操作。

 

PWM+DMA

也就是PWM输出的占空比可以由DMA方式来动态调节,而不需要单片机CPU参与进来,我们只需要把DMA要移动的数组定义好,然后启动DMA的循环模式和内存偏移,改变数组的数据就可以改变灯带的显示效果。

 

手册上介绍数据发送速度是:800Kbps

所以PWM的周期为:800KHZ,也就是1.25us

 

所以刚好一个周期就是一位数据,所以有:

当PWM设置的有效电平为高时:

1码:占空比为66%,也就是2/3周期

0码:占空比为33%,也就是1/3周期

八、PWM+DMA+ADC灯控与声控编程

(一)资源介绍

l  芯片:STM32F103C8T6

l  灯板:24位WS2812

l  灯板的控制IO:PA8

l  ADC声音检测IO:PA0

(二)  CubeMX设置

 

(三)  程序设计

 


 

观看演示效果:https://www.bilibili.com/video/BV1dv411Y7x3

 

原文链接:https://www.cnblogs.com/dongxiaodong/p/14362196.html


九、我的微信

  • 6
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
首先,需要了解WS2812灯带的通讯协议。WS2812灯带使用单线串行通信,每一个像素点需要发送24位的数据,其中8位表示红色亮度值,8位表示绿色亮度值,8位表示蓝色亮度值。发送的数据需要符合一定的时序要求,详细的通讯协议可以参考WS2812的数据手册。 接下来是控制程序的编写: 1. 首先定义三种不同亮度的颜色值,例如: ```c #define COLOR1 0x20FF00 // 亮度较低的颜色值 #define COLOR2 0xFFC800 // 亮度中等的颜色值 #define COLOR3 0xFF0000 // 亮度较高的颜色值 ``` 2. 定义发送数据的函数,根据WS2812的通讯协议,需要发送24位的数据,每一位的时间长度都需要精确控制。 ```c void WS2812_Send_Data(uint32_t data) { uint8_t i; for (i = 0; i < 24; i++) { if (((data << i) & 0x800000) == 0x800000) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET); delay_us(1); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET); delay_us(0.4); } else { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET); delay_us(0.4); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET); delay_us(1); } } } ``` 3. 然后是控制灯带亮度的函数,需要将颜色值转换为对应的24位数据,并按照通讯协议发送给灯带。这里假设灯带有10个像素点。 ```c void WS2812_Set_Brightness(uint8_t brightness) { uint32_t color1 = ((COLOR1 >> 8) & 0xFF) * brightness / 255; uint32_t color2 = ((COLOR1 >> 16) & 0xFF) * brightness / 255; uint32_t color3 = (COLOR1 & 0xFF) * brightness / 255; uint32_t data1 = (color2 << 16) | (color1 << 8) | color3; color1 = ((COLOR2 >> 8) & 0xFF) * brightness / 255; color2 = ((COLOR2 >> 16) & 0xFF) * brightness / 255; color3 = (COLOR2 & 0xFF) * brightness / 255; uint32_t data2 = (color2 << 16) | (color1 << 8) | color3; color1 = ((COLOR3 >> 8) & 0xFF) * brightness / 255; color2 = ((COLOR3 >> 16) & 0xFF) * brightness / 255; color3 = (COLOR3 & 0xFF) * brightness / 255; uint32_t data3 = (color2 << 16) | (color1 << 8) | color3; uint8_t i; for (i = 0; i < 10; i++) { if (i < 3) { WS2812_Send_Data(data1); } else if (i < 7) { WS2812_Send_Data(data2); } else { WS2812_Send_Data(data3); } } } ``` 4. 最后是主函数,需要初始化串口和定时器,并在循环中不断改变灯带的亮度。 ```c int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); MX_TIM2_Init(); HAL_TIM_Base_Start(&htim2); while (1) { WS2812_Set_Brightness(50); // 亮度较低 HAL_Delay(1000); WS2812_Set_Brightness(128); // 亮度中等 HAL_Delay(1000); WS2812_Set_Brightness(255); // 亮度较高 HAL_Delay(1000); } } ``` 以上就是控制WS2812灯带的程序,具体细节可能需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值