【STM32+STM32CubeMX】控制ws2812b灯珠
WS2812B简介
- 每个像素点都能实现256级亮度显示。
- 当刷新率为30帧/秒时,级联数不小于1024点。
- 数据发送速度为800Kbps。
- 通过DIN口输入数据,将复位后的第一组24bit数据保存,此后输入的数据都会从DO口发送给下一个级联像素点。
- 数据传输时间:
T0H |
0码,高电平时间 |
220ns~420ns |
T1H |
1码,高电平时间 |
750ns~1.6μs |
T0L |
0码,低电平时间 |
750ns~1.6μs |
T1L |
1码,低电平时间 |
220ns~420ns |
RES |
帧单位,低电平时间 |
300μs以上 |
一、开发流程
1、PWM+DMA原理
2、配置RCC
3、配置SYS
4、配置时钟树
5、配置定时器TIMx
6、Keil5代码
二、具体操作
2.1、控制原理
PWM+DMA可以实现数量和占空比可控的脉冲,具体实现原理是在开启DMA的情况下,定时器在每次计数满后,会自动将DMA传输过来的数据作为新一轮的比较数值。如果DMA传输的数据每次不同,那么每次的方波占空比就不一样的。在本例程中,我们将数据存放在一个数组,通过DMA传输数组的内容,根据数组中数据的个数和每个数据的大小,就能实现数量和占空比可控的PWM。
DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。
2.2、配置RCC
2.3配置SYS
2.4配置时钟树
2.5配置定时器TIM1
计算方法:
1、已知WS2812B的最大传输速率为800kbps,一次数据传输的时间在1.25μs。
2、设置定时器不分频(Prescaler为0即不分频)和计数周期(Couter Period)为89+1(软件会自动+1,填写的时候要减去1)。
3、波形频率算式:72M / (89+1)=800K,一个周期为1 / 800 = 1.25μs。
4、具体过程:
- 我们先配置Parameter settings,Parameter配置不分频,则f=1/72Mhz=0.0138888889us
- 时序符合388.8888us的复位时间。
- 通过计算,将89分为61和28时,时间为0.8472222229us和0.388888892us,符合传输条件。
- 89*0.0138888889us=1.2361111111us,符合一个数据传输的时间。
2.6在定时器中,Keil5代码开启DMA
2.7Keil5代码(此部分是复制别人的)
(1)创建RGB.c和RGB.h文件
(2)添加上述的RGB.c文件进工程
(3)RGB.c和RGB.h代码
RGB.h代码
#ifndef __RGB_H
#define __RGB_H
#include "main.h"
#define Hight_Data ( 64 ) //1 码相对计数值
#define Low_Data ( 36 ) //0 码相对计数值
#define Reste_Data ( 80 ) //80 复位电平相对计数值
#define Led_Num ( 4 ) //WS2812灯个数
#define Led_Data_Len ( 24 ) //WS2812数据长度,单个需要24个字节
#define WS2812_Data_Len (Led_Num * Led_Data_Len) //ws2812级联后需要的数组长度//uint16_t RGB_buffur[Reste_Data + WS2812_Data_Len] = { 0 }; //数据缓存数组void WS2812_Display_1(uint32_t Color, uint16_t num);
void WS2812_Display_2( uint8_t red, uint8_t green, uint8_t blue,uint16_t num);void WS2812_Number_4(uint32_t Color1,uint32_t Color2,uint32_t Color3,uint32_t Color4);//封装好的四个灯函数,只需要分别输入四个灯的颜色即可#endif
RGB.c代码
#include "RGB.h"
#include "main.h"
#include "tim.h"uint16_t RGB_buffur[Reste_Data + WS2812_Data_Len] = { 0 }; //数据缓存数组void WS2812_Display_1(uint32_t Color, uint16_t num)
{//指针偏移:需要跳过复位信号的N个0uint16_t* p = (RGB_buffur + Reste_Data) + (num * Led_Data_Len);for (uint8_t i = 0; i < 8; ++i) p[i+8]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);for (uint8_t i = 8; i < 16; ++i)p[i-8]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);for (uint8_t i = 16; i < 24; ++i)p[i]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data); }void WS2812_Display_2( uint8_t red, uint8_t green, uint8_t blue,uint16_t num)
{uint8_t i;uint32_t Color=(green << 16 | red << 8 | blue);//将2个8位数据合并转化为32位数据类型//指针偏移:需要跳过复位信号的N个0uint16_t* p = (RGB_buffur + Reste_Data) + (num * Led_Data_Len);for (i = 0; i < 24; ++i) //对数组进行编辑p[i]= (((Color << i) & 0X800000) ? Hight_Data : Low_Data); }void WS2812_Number_4(uint32_t Color1,uint32_t Color2,uint32_t Color3,uint32_t Color4)
{uint16_t RGB_Buff_4[Reste_Data + 4 * WS2812_Data_Len] = { 0 };uint16_t* p;uint32_t Color;for( uint8_t k=0;k<4;k++){ switch (k) //进行指针偏移{case 0: p= (RGB_Buff_4 + Reste_Data) + (0 * Led_Data_Len),Color=Color1;break;case 1: p= (RGB_Buff_4 + Reste_Data) + (1 * Led_Data_Len),Color=Color2;break;case 2: p= (RGB_Buff_4 + Reste_Data) + (2 * Led_Data_Len),Color=Color3;break;case 3: p= (RGB_Buff_4 + Reste_Data) + (3 * Led_Data_Len),Color=Color4;break;default : ;break; }for (uint8_t i = 0; i < 8; ++i) //对数组进行编辑{ for (uint8_t i = 0; i < 8; ++i)p[i+8]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);for (uint8_t i = 8; i < 16; ++i)p[i-8]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);for (uint8_t i = 16; i < 24; ++i)p[i]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);} } HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_Buff_4,(176));//启动DMA传输}// DMA 传输完成回调函数
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{HAL_TIM_PWM_Stop_DMA(&htim1,TIM_CHANNEL_1);
}
Main函数代码
#include "RGB.h"int main(void)
{extern uint16_t RGB_buffur[Reste_Data + WS2812_Data_Len];HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_DMA_Init();MX_TIM1_Init();// //点亮4个灯
// WS2812_Display_1(0x180000, 0);
// WS2812_Display_1(0x001800, 1);
// WS2812_Display_1(0x000018, 2);
// WS2812_Display_1(0x181818, 3);
// HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,(176));//启动DMA传输 // //以下代码和上述效果一致,只是颜色数据表示形式不一样
// WS2812_Display_2( 22 , 0 , 0, 0);
// WS2812_Display_2( 0 , 22, 0, 1);
// WS2812_Display_2( 0 , 0, 22, 2);
// WS2812_Display_2( 22, 22 , 22, 3);
// HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,(176));//启动DMA传输 while (1){//流水效果WS2812_Number_4(0x180000,0x001800,0x000018,0);HAL_Delay(500);WS2812_Number_4(0,0x180000,0x001800,0x000018);HAL_Delay(500);WS2812_Number_4(0x000018,0,0x180000,0x001800);HAL_Delay(500);WS2812_Number_4(0x001800,0x000018,0,0x180000);HAL_Delay(500);}
}
【STM32+STM32CubeMX】控制ws2812b灯珠相关推荐
- STM32F427库函数PWM+DMA控制ws2812b灯带
STM32F427IIHx库函数PWM+DMA控制ws2812b灯带 一.参考资料 查看ws2812b用户手册可知: 二.代码部分 添加文件ws2812b.c,ws2812b.h 配置的F427IIH ...
- STM32定时器控制LED灯闪烁及PWM练习
一.STM32定时器控制LED灯闪烁 1.相关配置 1)配置RCC和SYS 2)配置IO 配置PC15,并命名为D1. 3)配置定时器 选定时器2,配置Clock Source为Internal Cl ...
- 三、使用Arduino控制WS2812B灯
1.硬件 该硬件是基于ESP32设计的板子.如下图所示. 2.原理图 2.1.WS2812B原理图 2.2.ESP32部分原理图 综上:只需要控制IO17便可控制RGB灯. 3.软件编程 3.1.添加 ...
- STM32中断控制LED灯亮灭
目录 一.中断介绍 1.中断分类 硬件中断(Hardware Interrupt) 软件中断(Software Interrupt) 2.中断优先级 3.中断源种类 4.中断响应原则 二.新建项目 1 ...
- STM32按键控制LED灯(中断实现)
文章目录 1- 轮询模式和中断模式 2- 配置管脚为中断模式 3- 添加代码 4- 具体实现原理 5- main()--第一个执行程序? 在一般情况下,我们希望实现按键控制灯的亮和灭,这次学习的是中断 ...
- STM32按钮控制LED灯的开关
Hi, I'm Shendi 在之前已经可以控制 PC13 LED灯了,这次加上按钮来控制 首先上效果 STM32按钮控制LED 我使用的是四脚按钮,默认引脚弯折相同的相通,不同不同,按下后四脚都通 ...
- STM32中断控制LED灯
文章目录 一.相关概念 1.中断概念 2.中断过程 3.中断作用 4.中断优先级 5.中断响应过程 二. CubeMX中断控制LED灯 1.创建项目 2.代码修改 3.运行结果 三.HAL库中断串口通 ...
- STM32按键控制LED灯亮灭(四)
编程要点: 1)使能GPIO端口时钟: 2)初始化GPIO目标引脚为输入模式(浮空输入): 3)编写简单测试程序,检测按键的状态,实现按键控制LED灯: bsp_led.h文件 #ifndef T_L ...
- STM32中断控制LED灯闪烁
文章目录 一.中断 1.中断全过程 2.中断优先级 3.HAL库外部中断处理流程 4.中断回调函数 二.实现LED灯 三.实现项目 四.实验结果 五.总结 一.中断 1.中断全过程 中断发生 当CPU ...
- stm32【RGB_LED_WS2812灯珠】
RGB_LED 内置驱动IC:WS2812 测试平台:stm32f103c8t6 库版本:官方标准库3.5.0版本 LED规格:RGB-5050 内置IC:ws2812 驱动方式:归零码 相比普通的L ...
最新文章
- 三大深度学习生成模型:VAE、GAN及其变种
- 《Apache Common CLI官方文档
- WINKEY功能键你会用吗??
- 我的第一个Scrapy 程序 - 爬取当当网信息
- 购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session
- Eclipse is running in a JRE, but a JDK is required 解决方法(转)
- 更改文件和目录(及子目录)的拥有者
- 《Imperfect C++中文版》——1.3 运行期契约:前置条件、后置条件和不变式
- POJ 1426	Find The Multiple BFS
- this is a test
- matlab外接矩形,matlab求二值圖像最小外接矩形
- Java之添加环境变量
- DeepFake技术--实际操作
- 解决ubuntu 用anaconda 安装R 语言后,无法安装R语言package的问题
- 计算机编码,二进制编码数字
- 工程流体力学笔记暂记35 (平板层流边界层和平板混合边界层)
- “不能初始化photoshop,因为暂存盘已满”图文解决方案
- 电动车登记上牌系统源码免费分享
- 腾讯微博android版本,腾讯微博
- pythonencoding etf-8_Python 量化分析ETF指数基金投资