基于STM32CubeMX和keil采用通用定时器中断实现固定PWM可调PWM波输出分别实现LED闪烁与呼吸灯

文章目录

  • 前言
  • 1. PWM波阐述
  • 2. 通用定时器
    • 2.1 为什么用TIM14
    • 2.2 TIM14功能介绍
    • 2.3 一些配置参数解释
    • 2.4 PWM实现流程&中断
      • 2.4.1 非中断PWM输出(LED闪烁)
      • 2.4.2 中断PWM输出(LED呼吸灯)
  • 3. STM32CubeMX配置
    • 3.1 GPIO配置
    • 3.2 时钟配置
    • 3.3 定时器相关参数配置
    • 3.4 Debug配置
    • 3.5 中断配置
    • 3.6 代码生成
  • 4.代码编写
    • 4.1 LED闪烁代码编写
    • 4.2 LED呼吸灯代码编写
  • 总结

前言

上一篇博客里面写了基本定时器实现LED闪烁,主要就是一个预分频以及计数的使用,再加上一个电平翻转,原理以及具体操作比较简单。
这篇博客选择通用定时器进行稍微难一点的效果演示,用到输出PWM波的功能。
这篇博客写输出固定PWM以及可变PWM,进一步实现LED0闪烁以及LED0呼吸灯效果。
功能实现效果:
PF9输出PWM波控制LED0闪烁,1s周期,0.5s改变一次状态。
PF9输出PWM波控制LED0实现呼吸灯,一个时钟周期20ms。


1. PWM波阐述

PWM波,即脉宽调制波(Pulse Width Modulation),是一种在电信号中调整脉冲宽度的技术。它是通过控制信号的高电平时间和低电平时间的占空比来传输信息或实现对输出的精确控制。
在PWM波中,周期是固定的,周期是指一个完整高低电平的时间长度。而脉冲宽度则是高电平或低电平的持续时间,可以根据需要进行调整。脉冲宽度与信号的幅度呈正比,即脉冲宽度越宽,信号幅度越大,脉冲宽度越窄,信号幅度越小。

PWM波的优点包括:
1.简单可靠:PWM调制电路相对简单,成本低廉,可靠性高。
2.高效节能:由于PWM波的输出平均值可以通过调节占空比来控制,因此可以实现高效能的能量转换,减少功率损耗。
3.精确控制:通过调整脉冲宽度,可以精确控制输出的电压、电流或功率。
4.适应性强:PWM技术适用于不同类型的负载,可以调整频率和占空比来满足各种需求。

简单点概括一下就是,输出高低电平的一个方波,这个占空比可调。


2. 通用定时器

2.1 为什么用TIM14

首先是功能需求,这篇博客因为是LED0的闪烁以及呼吸灯效果,所以其实PWM波的输出都要给到PF9引脚上面去。
我们通过下面的原理图可以看到,PF9不仅接着LED0,同时也可以作为TIM14_CH1的输出。
在这里插入图片描述
在这里插入图片描述
如果直接在STM32CubeMX里面启用TIM14,可能并不是PF9,因为TIM14在STM32F407里面有两个引脚可以配置。如果配置了PA7,那么输出的PWM波其实并不能给到LED0上。这里为了方便起见,我们使用LED0的PF9的TIM14_CH1进行配置。
在这里插入图片描述

2.2 TIM14功能介绍

TIM14属于通用定时器的一种,它具有如下功能,其中这篇博客我们用到的是PWM生成功能。
1.计时功能:TIM14可以用作一个简单的计时器,用于测量时间间隔或持续时间。通过递增计数器的值来记录经过的时间,并根据预分频系数和时钟源来确定计时的精度。
2.定时中断:TIM14可以配置为在达到特定计数值时产生中断请求。通过设置计数器的自动重载值和使能中断,可以触发中断事件来执行特定的任务或操作。
3.PWM生成:TIM14可以用于生成简单的脉冲宽度调制(PWM)信号。通过设置计数器的自动重载值和比较寄存器的值,可以实现对脉冲的频率和占空比的控制。
4.单脉冲模式:TIM14还支持单脉冲模式,在特定的触发条件下,生成一个单脉冲信号。可以配置触发源、触发极性和脉冲宽度,用于各种应用场景。
5.捕获/比较模式:TIM14可以在输入捕获模式下,检测外部事件或信号的边沿,并记录计数器的当前值。同时,也可以在比较模式下,与比较寄存器中的值进行比较,触发相应的事件或输出行为。

2.3 一些配置参数解释

关于预分频系数等这些东西,详情参考基于STM32CubeMX和keil采用STM32F407的基本定时器中断实现LED闪烁,这里就不再赘述。
这里仅阐述相比于上一篇博客,PWM新增的部分功能阐述,即PWM Generation Channel 1配置

在这里插入图片描述

Mode:这里可以选择PWM mode 1和PWM mode 2模式,两者的区别在于:
前者在递增计数下,只要CNT<CCR,即计数器的值小于设定的比较寄存器的值,通道就是有效。反之有效。
前者在递减计数下,只要CNT<CCR,即计数器的值小于设定的比较寄存器的值,通道就是无效。反之有效。
后者与前者正好相反,例如递增计数情况下,CNT<CCR,通道无效。反之有效。

Pulse:PWM脉冲宽度,即设置CCR的值。这里的值应该小于整个计数周期。
Output compare preload:输出比较预装载。和auto-reload preload类似。这个值为enable时,我们修改CCR的值(这里也就是pluse的值),修改的值需要等到下一个UEV事件时才生效,否则立刻生效。
Fast Mode:是否使用输出比较快速模式,就是设置寄存器TIMx_CCMR1中的OC1FE位,用于加快触发输入事件对CC输出的影响,一般设置为Disable即可。
CH Polarity:通道极性。就是有效的状态是什么,如果设置为High,则通道有效的时候,输出为高电平。


2.4 PWM实现流程&中断

PWM实现的整体过程大致如下:
1.初始化定时器:首先,需要选择一个合适的定时器,并初始化它的基本配置。这包括选择定时器的模式、设置时钟源和预分频系数,以及配置计数器的位数。
2.设置PWM周期:根据需要设置PWM波的周期。这可以通过设置定时器的自动重载值(自动装载寄存器)来实现。自动重载值决定了计数器计数到多少后重新加载,并重新开始计数,从而确定PWM波的周期。
3.设置PWM占空比:根据期望的PWM波形的占空比,设置定时器的比较值(比较寄存器)。比较寄存器的值决定了计数器计数到多少时,PWM波的状态(高电平或低电平)发生变化。通过适当调整比较值,可以实现所需的占空比。
4.使能定时器和PWM输出:启用定时器并使能PWM输出。这通常包括使能定时器的计数器、开启PWM输出通道,以及配置相应的引脚和输出端口。
5.等待定时器中断或轮询:根据具体的实现方式,可以选择等待定时器中断请求,或者通过轮询定时器的状态来判断是否达到比较值,从而进行适当的处理或更新PWM波形的状态。

这个实验在做的时候我用STM32CubeMX配置了一堆,烧录了之后发现没作用,仔细查看代码,发现没给它使能。
下面写一下配置完成后如何使能启用PWM。

2.4.1 非中断PWM输出(LED闪烁)

PWM的输出是需要使能的,需要使用到函数HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel),这个函数的第一个参数是TIM的一个事件处理类的对象,这里也就是我们的TIM14的一个对象,后面的是通道。因为TIM14里面只有一个通道,所以这里我们应该为CH1。

在使用HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)这个函数之前,还需要使用HAL_TIM_Base_Start(TIM_HandleTypeDef *htim),这个函数是前者的前置条件,也就是先有Base_Start,再有PWM_Start。这也比较好理解,就是先有基本一些功能启用,再开启高级一点的功能。
LED闪烁其实就是固定占空比的情况,所以只需要输出固定占空比的PWM波,不需要中断。

2.4.2 中断PWM输出(LED呼吸灯)

中断PWM输出其实就是每一个PWM的周期结束,都会触发一次中断。那么和上面一样,也需要先开启基本的功能,再开启高级的功能。因为是中断方式,所以除了初始化中断以及配置中断向量优先级之类的,只需要调用对应的中断相关的启动函数。中断相关的函数后面一般都会有个IT(Interrupt)

HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);

使用中断的好处就是我可以每一次中断触发的时候在回调函数里修改CCR的值,从而改变占空比,从而实现呼吸灯效果。


3. STM32CubeMX配置

3.1 GPIO配置

在这里插入图片描述

3.2 时钟配置

开启外部晶振(其实也可以不开启,看你时钟的最终频率设置多少,一般开启外部晶振是为了设置时钟的时候能适配更多的时钟频率)
在这里插入图片描述下图的时钟树中我的时钟来自于内部高速晶振,其实和外部晶振开启与否并没有关系,因为我最终得到100MHz的频率使用内部高速晶振经过分频器和锁相环就可以得到。
下面时钟的HSI RC提供16MHz,经过分配器,变为2MHz,再倍频100,再除以2,片选PLLCLK,一倍分频,就得到了我们最终所设置的100MHz。
由于TIM14是在APB1总线上,所以我们还要关注一下APB1总线的时钟频率,这里自动设置为了50MHz。
也就是说TIM14获得的最初始的时钟是50MHz,后面的定时器的分频是在50MHz基础上进行的。
在这里插入图片描述

3.3 定时器相关参数配置

如果实现0.5s闪烁则配置如下
这里分频系数的设定是为了获得单次时钟周期为1ms时钟,ARR设置为999是为了获得周期为1s的PWM波周期。
Pulse为500是为了获得占空比为 500 ∗ 1 m s 1000 m s = 500 m s 1000 m s = 0.5 \frac{500*1ms}{1000ms}=\frac{500ms}{1000ms}=0.5 1000ms5001ms=1000ms500ms=0.5的PWM波。

在这里插入图片描述
如果实现呼吸灯效果则配置如下
这里分频系数的设定是为了获得单次时钟周期为0.1ms时钟,ARR设置为199是为了获得周期为20ms的PWM波周期。
Pulse为50是为了获得占空比为 50 ∗ 0.1 m s 20 = 5 m s 20 m s = 0.25 \frac{50*0.1ms}{20}=\frac{5ms}{20ms}=0.25 20500.1ms=20ms5ms=0.25的PWM波。
在这里插入图片描述

为什么要分开设置,是因为我自己这样设置效果比较明显,你也可以根据自己的需要进行修改。


3.4 Debug配置

在这里插入图片描述

3.5 中断配置

在这里插入图片描述

3.6 代码生成

在这里插入图片描述
在这里插入图片描述


4.代码编写

4.1 LED闪烁代码编写

如果不使用中断,代码比较简单,其实只需要在main函数里面使能即可。
在这里插入图片描述

	//不使用中断即输出固定占空比的PWMHAL_TIM_Base_Start(&htim14);HAL_TIM_PWM_Start(&htim14,TIM_CHANNEL_1);

LED闪烁的初始化里面参数:
在这里插入图片描述

4.2 LED呼吸灯代码编写

呼吸灯要用到中断,因为要调整PWM的占空比即CCR变量的值。
首先是中断使能

	//使用中断,在回调函数里改变占空比//HAL_TIM_Base_Start_IT(&htim14);//HAL_TIM_PWM_Start_IT(&htim14,TIM_CHANNEL_1);

回调函数是HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim),这个函数在计数器到达脉冲设置的值是触发。
为了调整脉宽等,我们还需要设定参数。

uint16_t plusWidth=500;//脉宽
uint16_t dirInc=1;//脉宽变化方向,1为递增,0递减

回调函数代码:

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{//只针对TIM14进行中断处理if(htim->Instance!=TIM14){return;}//如果是脉宽递增则增加脉宽if(dirInc==1){plusWidth++;if(plusWidth>=195){plusWidth=195;dirInc=0;}}//如果是脉宽递减则减少脉宽if(dirInc==0){plusWidth--;if(plusWidth<=5){plusWidth=5;dirInc=1;}}//__HAL_TIM_SetCompare(定时器对象指针,定时器通道,需要设置的CCR值);__HAL_TIM_SetCompare(&htim14,TIM_CHANNEL_1,plusWidth);
}	

呼吸灯的初始化参数配置
在这里插入图片描述


总结

这篇博客对定时器的PWM功能进行了归纳总结以及应用实现,写的非常详细,对应的MX工程以及Keil代码我放在了开头,需要自取。

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

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

相关文章

ESP32-C2开发板 ESP8684芯片 兼容ESP32-C3开发

C2是一个芯片采用4毫米x 4毫米封装&#xff0c;与272 kB内存。它运行框架&#xff0c;例如ESP-Jumpstart和ESP造雨者&#xff0c;同时它也运行ESP-IDF。ESP-IDF是Espressif面向嵌入式物联网设备的开源实时操作系统&#xff0c;受到了全球用户的信赖。它由支持Espressif以及所有…

2023/8/5总结

主要实现了&#xff1a; 举报&#xff1a; 内容管理搜索的实现 管理员界面 还有消息没写&#xff0c;以及一些小细节

Linux修改系统语言

sudo dpkg-reconfigure locales 按pagedown键&#xff0c;移动红色光标到 zh_CN.UTF-8 UTF-8&#xff0c;空格标记*号&#xff08;没标记下一页没有这一项&#xff09;&#xff0c;回车。 下一页选择 zh_CN.UTF-8。 如果找不到 dpkg-reconfigure whereis dpkg-reconfigure …

HTML 初

前言 HTML的基本骨架 HTML基本骨架是构建网页的最基本的结果。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…

iOS——Block回调

先跟着我实现最简单的 Block 回调传参的使用&#xff0c;如果你能举一反三&#xff0c;基本上可以满足了 OC 中的开发需求。已经实现的同学可以跳到下一节。 首先解释一下我们例子要实现什么功能&#xff08;其实是烂大街又最形象的例子&#xff09;&#xff1a; 有两个视图控…

互感和励磁电感(激磁电感)的关系

互感器&#xff0c;变压器&#xff0c;他们之间有着千丝万缕的联系&#xff0c;自感&#xff0c;互感&#xff0c;激磁电感&#xff0c;漏感、耦合系数、理想互感器、理想变压器&#xff0c;这些东西的概念理解和相互之间的关系式。都搞明白了吗&#xff1f;

elasticsearch 将时间类型为时间戳保存格式的时间字段格式化返回

dsl查询用法如下&#xff1a; GET /your_index/_search {"_source": {"includes": ["timestamp", // Include the timestamp field in the search results// Other fields you want to include],"excludes": []},"query": …

外国机构在中国境内提供金融信息服务23家许可名单

6月30日&#xff0c;国家互联网信息办公室公布23家外国&#xff08;境外&#xff09;机构在中国境内提供金融信息服务许可名单&#xff0c;如下&#xff1a;

LeetCode643. 子数组最大平均数 I

题干 给你一个由 n 个元素组成的整数数组 nums 和一个整数 k 。 请你找出平均数最大且 长度为 k 的连续子数组&#xff0c;并输出该最大平均数。 任何误差小于 10^-5 的答案都将被视为正确答案。 示例1&#xff1a; 输入&#xff1a;nums [1,12,-5,-6,50,3], k 4 输出&am…

前端小练习:案例4.3D图片旋转展示(旋转木马)

一.效果预览图 二.实现思路 1.实现旋转木马效果的第一步是先准备好自己需要的图片&#xff0c;创建html文件 2.旋转木马的实现&#xff0c;关键点在3D形变和关键帧动画。 3.步骤&#xff0c;定义一个div使其居中&#xff0c;&#xff0c;把图片放进div盒子里&#xff0c;因为图…

Vue系列第七篇:Element UI之el-main,el-table,el-dialog,el-pagination,el-breadcrumb等控件使用

本篇实现主页面功能&#xff0c;包括主页面排版布局&#xff0c;学生管理模块实现&#xff0c;后台接口实现等功能。 目录 1.运行效果 1.1登录页面 1.2主页面 1.3学生管理 - 信息列表 1.4学生管理 - 信息管理 1.5学生管理 - 作业列表 1.6学生管理 - 作业管理 2.前端代码…

npm install时出现的问题Failed at the node-sass@4.14.1 postinstall script

从阿里云上拉取下来项目后&#xff0c;首先使用npm install 命令进行安装所需依赖&#xff0c;意想不到的事情发生了&#xff0c;报出了Failed at the node-sass4.14.1 postinstall script&#xff0c;这个问题&#xff0c;顿时一脸懵逼&#xff1b;询问前端大佬&#xff0c;给…

危大工程智慧工地源码,微服务+Java+Spring Cloud +UniApp +MySql 物联网、人工智能、视频AI分析

一套智慧工地管理平台源码&#xff0c;PC端移动APP端可视货数据管理端源码 智慧工地可视化系统利用物联网、人工智能、云计算、大数据、移动互联网等新一代信息技术&#xff0c;通过工地中台、三维建模服务、视频AI分析服务等技术支撑&#xff0c;实现智慧工地高精度动态仿真&a…

【新人指南】给新人软件开发工程师的干货建议

在我是新人时&#xff0c;如果有前辈能够指导方向一下&#xff0c;分享一些踩坑经历&#xff0c;或许会让我少走很多弯路&#xff0c;节省更多的学习的成本。 这篇文章根据我多年的工作经验&#xff0c;给新人总结了一些建议&#xff0c;希望对你会有所帮助。 写好注释 没有注…

ELFK——ELK结合filebeat日志分析系统(2)

目录 一、filebeat 二、ELFK 1.原理简介 2.在ELK基础上部署filebeat 一、filebeat Filebeat&#xff0c;轻量级的开源日志文件数据搜集器。通常在需要采集数据的客户端安装 Filebeat&#xff0c;并指定目录与日志格式&#xff0c;Filebeat 就能快速收集数据&#xff0c;并…

解决宝塔面板升级获取更新包失败,请稍后更新或联系宝塔运维

宝塔Linux面板执行升级命令后失败&#xff0c;提示“获取更新包失败&#xff0c;请稍后更新或联系宝塔运维”如何解决&#xff1f;新手站长分享宝塔面板升级失败的解决方法&#xff1a; 宝塔面板升级失败解决方法 1、使用root账户登录到你的云服务器上&#xff0c;宝塔Linux面…

LLVM笔记1

参考&#xff1a;https://www.bilibili.com/video/BV1D84y1y73v/?share_sourcecopy_web&vd_sourcefc187607fc6ec6bbd2c74a3d0d7484cf 文章目录 零、入门名词解释1. Compiler & Interpreter2. AOT静态编译和JIT动态解释的编译方式3. Pass4. Intermediate Representatio…

关于HIVE的分区与分桶

1.分区 1.概念 Hive中的分区就是把一张大表的数据按照业务需要分散的存储到多个目录&#xff0c;每个目录就称为该表的一个分区。在查询时通过where子句中的表达式选择查询所需要的分区&#xff0c;这样的查询效率会提高很多 个人理解白话:按表中或者自定义的一个列,对数据进…

C#中XML文档与Treeview控件操作的数据同步

在前文《C#使用XML和Treeview结合实现复杂数据采集功能》中&#xff0c;使用Treeview展示了XML的数据&#xff0c;问题是如果在Treeview上进行了操作&#xff0c;怎样同步更改XML数据的内容呢&#xff1f; 这个问题看似简单&#xff0c;实现起来有一点小麻烦。 要实现的操作功能…

C语言假期作业 DAY 13

一、选择题 1、如果 x2014 &#xff0c;下面函数的返回值是&#xff08; &#xff09; int fun(unsigned int x) { int n 0; while(x 1) { n; x x | (x 1); } return n; } A: 20 B: 21 C: 23 D 25 答案解析 正确答案&#xff1a;C 这个作用是对整型中0的个数进行统计&…