# LowMEM ws2812b library ( STM32F4_WS2812B )
This is a memory and CPU efficient implementation of WS2812B library for STM32 processors. **You have to compile it with -Og or at least -O1 optimizations to take advantage of it.**
**See my other repositories for F0 and F3 port.**
The example is implemented for STM32F4 line with TIM1 and DMA2. The DMA2 is necessary because only this DMA has access to the AHB1 bus where the GPIO peripheral is located.
Project is made in Atollic TrueStudio but you can compile it with any ARM-GCC. It is possible to change the code to work based on other timer or STM F1, F2 or F4 line. This version is using STM HAL library.
**If you like this library, please let me know, follow me @hubmartin.**
**Also subscribing to my electronics youtube channel https://www.youtube.com/user/hubmartin with practical videos and teardowns will motivate me to make more content for community. Thank you.**
Here I explain the using of lib. Under this example below is explained how lib works under the hood
The library is in the /src/ws2812b directory and example of init, redraw and effects are in src/visEffect.c file.
in ws2812b.h you have to set few defines:
```
// GPIO clock peripheral enable command
#define WS2812B_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
// LED output port
#define WS2812B_PORT GPIOC
// LED output pins
#define WS2812B_PINS (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3)
// How many LEDs are in the series
#define WS2812B_NUMBER_OF_LEDS 60
// Number of paralel LED strips on the SAME gpio. Each has its own buffer.
#define WS2812_BUFFER_COUNT 2
```
Then in your code initialize the structure and call the init function:
```
// RGB Framebuffers
uint8_t frameBuffer[3*60];
uint8_t frameBuffer2[3*20];
void visInit()
{
// Set output channel/pin, GPIO_PIN_0 = 0, for GPIO_PIN_5 = 5 - this has to correspond to WS2812B_PINS
ws2812b.item[0].channel = 0;
// Your RGB framebuffer
ws2812b.item[0].frameBufferPointer = frameBuffer;
// RAW size of framebuffer
ws2812b.item[0].frameBufferSize = sizeof(frameBuffer);
// If you need more parallel LED strips, increase the WS2812_BUFFER_COUNT value
ws2812b.item[1].channel = 3;
ws2812b.item[1].frameBufferPointer = frameBuffer2;
ws2812b.item[1].frameBufferSize = sizeof(frameBuffer2);
ws2812b_init();
}
```
You can also use one framebuffer on many outputs.
When the framebuffer is shorter than the WS2812B_NUMBER_OF_LEDS the framebuffer wraps over, nothing breaks. This is great if you would like to have 500 LEDs in one strip but you only need to repeat 8,16,.. animated pixels.
You can also have one big framebuffer and point the "frameBufferPointer" to different places in your buffer.
### Then you just call the ws2812b_handle() function. You have to trigger new transfer by setting the ws2812b.startTransfer = 1;
```
void visHandle()
{
if(ws2812b.transferComplete)
{
// Update your framebuffer here or swap buffers
visHandle2();
// Signal that buffer is changed and transfer new data
ws2812b.startTransfer = 1;
ws2812b_handle();
}
}
```
##How the lib works
WS2812B has specific communication protocol and it is necessary to bend some standard peripherals to use this protocol. The most easy approach would be implement blocking cycle-exact code in assembly that will spit out ones and zeroes as we need. This is implemented in NeoPixel library for AVR and ARM processor.
Some improvements can be made if part of the bits are generated by some HW peripheral for example SPI or PWM. The best solution is to keep the CPU free and let the DMA and timer do the precise timing. So I've made some DMA tests and it appeared that I can use my code to precise generate necessary waveforms. The I looked around and discovered that this is the approach that already OctoWS2811 library is using. So at least I wasn't completely wrong. But I would like to have better lib. I have documented all approaches on my site http://www.martinhubacek.cz/arm/improved-stm32-ws2812b-library.
The octo lib is great when you use lot of parallel strips. Because it can output data for all your 16 strips. On the other side if you use only 2 or 4 LED strips (outputs) then you are wasting your RAM because of the data organization in the library.
Based on your longest LED strip the octo library creates an array uint16_r buffer[NUMBER_OF_LEDS × 24]. So if you use one strip with ten LEDs then it creates the uint16_t array of length 240 (480 bytes) where only one bit of each item in array is used. So you are wasting 93% of your array in RAM. If you have LED strip connected to the pin PB3 then the 3rd bit of each item in array is used. This is because DMA needs pre-processed data in specific format. I can do better.
The DMA has of course some small jitter but when you run this lib on anything above 40MHz it is fine. The jitter is within the WS2812 specification so don't worry. When I run similar code on old STM32F100 on maximal CPU freq 24MHz (F100 line is slow), I had big jitter when the DMA was battling with CPU interrupt bus access. I overclocked the STM32F100 little bit (exactly twice the speed to 48MHz :Đ) and it works without issues.
##My library has few improvements:
### One separate buffer for your (big) framebuffer and second small internal bitbuffer for DMA.
**RGB framebuffer** - this is one dimension array with {R1, G1, B1, R2, G2, B2, ...} format.
**Bitbuffer** - this is basicaly the same format buffer like the Octo2811 lib uses but it is allocated only for 2 LEDs (2 LEDs on each of 16 output channels)
**Here is the improvement.** I fill the **bitbuffer** on-the-fly in the double-buffering fashion based on DMA_HALF_TRANSFER and DMA_COMPLETE_TRANSFER interrupts. While the data to the first LED is fed, I prepare the next 24 bits in the second part of the bitbuffer for the second LED in the DMA Irq handler in the background. This IRQ bit-juggling was optimized so it's just a small overhead - I'll explain that down below. And while the data from the second part of bitbuffer is send to the second LED, the DMA Half transfer interrupt is fired and in it are prepared another 24 bit data for first LED.
### Bit-banding for bit-juggling in the IRQ
Interrupts has to be very fast. Thats why I tried many ways to "serialize" the bits from framebuffer to bitbuffer. The best solution is to use bit-banding (don't confuse with bit-banging). This is HW accelerated access to single bits in RAM and I've made a practical video some time ago https://www.youtube.com/watch?v=h78DyF1NOio
Because the bits are computed on the background during the transmittion, there is little CPU overhead. For one LED strip it is on 64MHz STM32F3 just about 8% **only during** transmission of the data. The overhead is bigger as you use more parallel LED strips on the same port. It can be like 10% for two LEDs but it don't rise linearly. You have to take into account overhead of IRQ service routine, clearing IRQ bits. The bit-juggling with bit-banding implementation is quite efficient.
Bit-banding can also improve the speed of set pixel function in the OctoWS2811 library. If you try that let me know.
**Comparison of different methods generating WS2812B waveforms is also on my site**
http://www.martinhubacek.cz/arm/improved-stm32-ws2812b-library
On the image below is in yellow waveform for WS2812B LED strip. Blue trace displays in HIGH state when the CPU is doing bit-juggling in the DMA IRQ. The first blue peak is DMA half transfer IRQ, the second peak is DMA complete transfer IRQ. On my board I don't have external crystal so instead of 72MHz I run only 64Mhz. The CPU overhead during transfer is 11% and the IRQ routine takes 3.6 microseconds.
![alt tag](https://github.com/hubmartin/ws2812b_stm32F3/blob/master/WS2812%20scope%20waveform.png)
##Pros and Cons
Pros are when you use less paralel strips on the same GPIO port. You can efficiently use your RAM. But when you use more and more LED strips on the same port, the background overhead of b
没有合适的资源?快使用搜索试试~ 我知道了~
WS2812B_STM32F4-master.zip_STM32F4驱动WS2812_WS2812 STM32F4_ws2812
共76个文件
h:41个
c:20个
md:2个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
5星 · 超过95%的资源 7 下载量 75 浏览量
2022-07-13
23:09:36
上传
评论 3
收藏 867KB ZIP 举报
温馨提示
ws2812 stm32f4的驱动程序,可轻松实现对ws2812的驱动
资源详情
资源评论
资源推荐
收起资源包目录
WS2812B_STM32F4-master.zip (76个子文件)
WS2812B_STM32F4-master
STM32F4_WS2812B.ioc 3KB
STM32F407VG_FLASH.ld 5KB
Src
main.c 6KB
visEffect.c 4KB
visEffect.h 301B
stm32f4xx_hal_msp.c 3KB
stm32f4xx_it.c 5KB
ws2812b
ws2812b.c 18KB
ws2812b.h 3KB
.settings
language.settings.xml 897B
com.atollic.truestudio.debug.hardware_device.prefs 205B
org.eclipse.cdt.managedbuilder.core.prefs 1KB
Drivers
CMSIS
Include
core_cm0.h 36KB
core_cm3.h 100KB
arm_common_tables.h 7KB
core_cm4.h 110KB
cmsis_gcc.h 39KB
cmsis_armcc_V6.h 52KB
core_cm7.h 134KB
cmsis_armcc.h 23KB
core_sc000.h 43KB
core_cm0plus.h 43KB
arm_const_structs.h 4KB
arm_math.h 239KB
core_cmSimd.h 3KB
core_cmFunc.h 3KB
core_cmInstr.h 3KB
core_sc300.h 99KB
Device
ST
STM32F4xx
Include
stm32f407xx.h 548KB
stm32f4xx.h 10KB
system_stm32f4xx.h 3KB
Source
Templates
system_stm32f4xx.c 27KB
gcc
startup_stm32f407xx.s 24KB
STM32F4xx_HAL_Driver
Src
stm32f4xx_hal_pwr_ex.c 24KB
stm32f4xx_hal_dma.c 40KB
stm32f4xx_hal_rcc.c 42KB
stm32f4xx_hal_flash_ex.c 50KB
stm32f4xx_hal_flash_ramfunc.c 7KB
stm32f4xx_hal_dma_ex.c 11KB
stm32f4xx_hal_tim.c 170KB
stm32f4xx_hal_pwr.c 21KB
stm32f4xx_hal.c 18KB
stm32f4xx_hal_cortex.c 19KB
stm32f4xx_hal_tim_ex.c 65KB
stm32f4xx_hal_gpio.c 20KB
stm32f4xx_hal_rcc_ex.c 109KB
stm32f4xx_hal_flash.c 24KB
Inc
stm32f4xx_hal_flash_ex.h 59KB
stm32f4xx_hal_pwr_ex.h 17KB
stm32f4xx_hal_pwr.h 15KB
stm32f4xx_hal_gpio.h 13KB
Legacy
stm32_hal_legacy.h 169KB
stm32f4xx_hal_def.h 8KB
stm32f4xx_hal_dma_ex.h 4KB
stm32f4xx_hal_flash.h 16KB
stm32f4xx_hal_rcc_ex.h 389KB
stm32f4xx_hal_gpio_ex.h 72KB
stm32f4xx_hal_dma.h 37KB
stm32f4xx_hal.h 13KB
stm32f4xx_hal_tim.h 72KB
stm32f4xx_hal_rcc.h 71KB
stm32f4xx_hal_flash_ramfunc.h 4KB
stm32f4xx_hal_cortex.h 19KB
stm32f4xx_hal_tim_ex.h 14KB
.mxproject 4KB
.project 2KB
.cproject 20KB
doc
STM32F407 168MHz 16 paralel output only 60percent CPU overhead during TX.png 377KB
LICENSE.md 1KB
.gitignore 82B
Inc
stm32f4xx_hal_conf.h 16KB
stm32f4xx_it.h 3KB
main.h 2KB
README.md 8KB
STM32F4_WS2812B.elf.launch 5KB
.gitattributes 378B
共 76 条
- 1
钱亚锋
- 粉丝: 86
- 资源: 1万+
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- tesseract安装包
- 1_32陀螺仪舵机.zip
- HITJ0302MP-VB一款P-Channel沟道SOT23的MOSFET晶体管参数介绍与应用说明
- XILINXFPGA源码PCIExpress标准概述
- HITJ0204MP-VB一款P-Channel沟道SOT23的MOSFET晶体管参数介绍与应用说明
- XILINXFPGA源码PCIExpressIP核应用参考设计
- XILINXFPGA源码LCD12864在Spartan-3E实现代码
- XILINXFPGA源码LCDIPCORE
- G6402-VB一款SOT23封装P-Channel场效应MOS管
- XILINXFPGA源码IPcamera的开源系统
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论15