STM32G0 定时器PWM DMA输出驱动WS2812配置 LL库

通过DMA方式输出PWM模拟LED数据信号

优点:不消耗CPU资源
缺点:占用内存较大

STM32CUBEMX配置

定时器配置

定时器通道:TIM3 CH2
分频:0
重装值:79,芯片主频64Mhz,因此PWM输出频率:64Mhz/79 ≈ 800Khz,满足芯片要求。
auto-reload preload 要关闭
output compare preload 要打开
在这里插入图片描述

DMA配置

外设一定要选择TIM3_UP,不要选TIM_CHx
方向是内存到外设,和ADC是反的
模式选择Circular,也可以选择Normal,每次要写的时候才发送,这里为了方便选Circular。
重要:数据宽度,外设选择half word,内存选择byte,可以省空间
在这里插入图片描述

添加初始化代码

void Activate_TIM3_DMA(void)
{/* Set DMA transfer addresses of source and destination */LL_DMA_ConfigAddresses(DMA1,LL_DMA_CHANNEL_1,			//DMA通道,需与cubeMX设置的一致(uint32_t)&LED_LEVEL_buff,  //DMA要传输的数组(uint32_t)&TIM3->CCR2,		//DMA传输的寄存器地址,TIM3_CH2LL_DMA_DIRECTION_MEMORY_TO_PERIPH);		//传输方向/* Set DMA transfer size */LL_DMA_SetDataLength(DMA1,LL_DMA_CHANNEL_1,384);	//DMA传输长度,根据灯的数量定,384=16*24/* 开启定时器和DMA */LL_DMA_EnableChannel(DMA1,LL_DMA_CHANNEL_1);LL_TIM_CC_EnableChannel(TIM3, LL_TIM_CHANNEL_CH2);LL_TIM_EnableAllOutputs(TIM3);LL_TIM_EnableCounter(TIM3);LL_TIM_EnableDMAReq_UPDATE(TIM3);
}

添加LED电平代码

#define TL    20 		//写0电平占空比= 20/(79+1) 79为定时器重装值
#define TH    55 		//写1电平时间/*LED数据传输电平数组*/ /*多余的4个数组是RESET信号,需大于80us*/
vu8 LED_LEVEL_buff[16][24] = {
TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led0*/
TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led1*/
TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led2*/
TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led3*/
TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led4*/
TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led5*/
TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led6*/
TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led7*/
TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led8*/
TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led9*/
TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led10*/
TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,   TL, TL, TL, TL, TL, TL, TL, TL,/*led11*/
0};

这里一共12个灯,每个灯需24bit,定义16组数据是因为WS2812发送完所有数据后需要80us的低电平信号,剩下4组数据为80us的低电平信号。
已知每个信号宽度为1.25us,算下来为800Khz,这个非常重要,因此TIM重装值必须为79。
计算0码的长度,也就是占空比,占空比= 20/(79+1),时间大概为0.31us,满足需求
计算1码的长度,也就是占空比,占空比= 55/(79+1),时间大概为0.86us,满足需求
在这里插入图片描述
在这里插入图片描述
当要更改灯光颜色的时候,修改LED_LEVEL_buff就行了,效率很高,缺点是需要占用较大的内存空间,由于CPU主频很低,重装值不会超过79,因此数组用8位就够了,32位纯属浪费空间,所以DMA内存长度一定要和数组匹配,否则会出现波形混乱。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/100782.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

el-table自适应列宽实现

【背景小记】 el-table的el-table-column如果不指定width的话,会自动设定一个宽度,表格内容会自动换行,对强迫症用户来说非常不友好,为了追求完美用户体验,所以这里需要实现两个效果: 1. 强制表格内容不换…

策略路由典型配置:通过流策略实现策略路由(即重定向到不同的下一跳)

策略路由典型配置:通过流策略实现策略路由(即重定向到不同的下一跳) 1、拓扑图及组网要求 公司用户通过SW2核心交换机连接到外部网络,其中一条是高速链路,网关是192.168.100.2/24,另一条是低俗网络&#…

Java8实战-总结22

Java8实战-总结22 使用流数值流原始类型流特化数值范围数值流应用:勾股数 使用流 数值流 可以使用reduce方法计算流中元素的总和。例如,可以像下面这样计算菜单的热量: int calories menu.stream().map(Dish::getcalories).reduce(0, Int…

win11安装jdk

Windows11JDK20安装及环境变量配置 - 简书 Java学习--Win11配置环境变量-腾讯云开发者社区-腾讯云 电脑上安装多个JDK版本时如何自由切换_安装多版本jdk_有青枫林的博客-CSDN博客 Windows同时安装两个版本JDK,并实现动态切换JAVA8或者JAVA11 【无标题】windows1…

【进阶篇】Redis缓存击穿, 穿透, 雪崩, 污染详解

【进阶篇】Redis缓存穿击, 穿透, 雪崩, 污染详解 文章目录 【进阶篇】Redis缓存穿击, 穿透, 雪崩, 污染详解0. 前言大纲缓存穿击缓存穿透缓存雪崩缓存污染 1. 什么是缓存穿透?1.1. 发生原因1.2. 导致问题1.3. 解决方案 2. 什么是缓存击穿3.1. 发生原因3.1. 解决方案…

php使用jwt作登录验证

1 在项目根目录下,安装jwt composer require firebase/php-jwt 2 在登录控制器中加入生成token的代码 use Firebase\JWT\JWT; use Firebase\JWT\Key; class Login extends Cross {/*** 显示资源列表** return \think\Response*/public function index(Request $r…

visual studio 2008 编译项目出现层次不穷问题枚举

文章目录 1、严重性 代码 说明 项目 文件 行 禁止显示状态 错误 C1047 对象或库文件“.lib”是使用与其他对象(如“x64\Release\main.obj”)不同的1、错误原因 2、意外的预编译头错误,只需重新运行编译器就可能修复此问题3、 warning LNK4099: 未找到 PDB“vc90.pdb”(使用“..…

C语言类型占内存大小

C语言类型占内存大小 C语言数据类型sizeof测试基本数据类型所占字符大小运行结果数据模型 C语言数据类型 sizeof测试基本数据类型所占字符大小 #include <stdio.h>int main() {char a;short b;int c;long d;float e;double f;printf("char %d\n", sizeof (a…

uniapp 路由不要显示#

在Uniapp中&#xff0c;路由默认使用的是hash模式&#xff0c;即在URL中添加#符号。如果你不想在URL中显示#&#xff0c;可以切换为使用history模式。 要在Uniapp中使用history模式&#xff0c;可以按照以下步骤进行操作&#xff1a; 打开manifest.json文件。在"app&qu…

《代码随想录》刷题笔记——数组篇【java实现】

*二分查找 题目链接 https://leetcode.cn/problems/binary-search/ 左闭右闭区间实现 时间复杂度&#xff1a;O(log n)空间复杂度&#xff1a;O(1) /*** 左闭右闭写法** param nums* param target* return*/ public static int search1(int[] nums, int target) {if (nums…

SQL Server如何新建作业

作业&#xff1a; 在 SQL Server 中&#xff0c;作业&#xff08;Job&#xff09;是一组可以在预定时间自动执行的任务。可以将作业看作是一个可以在后台运行的程序或脚本。作业由一系列步骤组成&#xff0c;每个步骤都是一个独立的任务&#xff0c;可以执行诸如执行 SQL 查询…

C++内存管理(3)——内存池

1. 默认内存管理函数的不足&#xff08;为什么使用内存池&#xff09; 利用默认的内存管理操作符 new/delete 和函数 malloc()/free() 在堆上分配和释放内存会有一些额外的开销。 系统在接收到分配一定大小内存的请求时&#xff0c;首先查找内部维护的内存空闲块表&#xff0…