基于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.rhkb.cn/news/76818.html

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

相关文章

C# Blazor 学习笔记(11):路由跳转和信息传值

文章目录 前言路由跳转测试用例路由传参/路由约束想法更新&#xff1a;2023年8月4日 前言 Blazor对路由跳转进行了封装。 ASP.NET Core Blazor 路由和导航 NavigationManager 类 本文的主要内容就是全局的跳转 路由跳转 路由跳转就要用到NavigationManager 类。 其实最常用…

【腾讯云Cloud Studio实战训练营】使用React快速构建点餐H5

文章目录 前言一、Cloud Studio是什么二、Cloud Studio特点三、Cloud Studio使用1.访问官网2.账号注册3.模板选择4.模板初始化5.H5开发安装 antd-mobile安装 Less安装 normalize&#xff1a;上传项目需要的素材&#xff1a;替换App.js主文件&#xff1a;项目启动、展示 6.发布仓…

K8s中的Secret

Secret作用&#xff1a;加密数据存在etcd里面&#xff0c;让pod容器以挂载Volume方式进行访问。场景&#xff1a;凭据

数据集相关网站(Open datasets and sources)

数据集相关网站(Open datasets and sources&#xff09; 数据集网站 Open datasets and sources政府数据网站 Government Data:金融数据网站 Financial Data Sources:犯罪数据网站 Crime Data:健康数据网站 Health Data:学术和商业数据网站 Academic and Business Data:其他数据…

用C语言构建一个数字识别卷积神经网络

卷积神经网络的具体原理和对应的python例子参见末尾的参考资料2.3. 这里仅叙述卷积神经网络的配置, 其余部分不做赘述&#xff0c;构建和训练神经网络的具体步骤请参见上一篇: 用C语言构建一个手写数字识别神经网路 卷积网络同样采用简单的三层结构&#xff0c;包括输入层con…

最新2024届【海康威视】内推码【GTK3B6】

最新2024届【海康威视】内推码【GTK3B6】 【内推码使用方法】 1.请学弟学妹们登录校招官网&#xff0c;选择岗位投递简历&#xff1b; 2.投递过程中填写内推码完成内推步骤&#xff0c;即可获得内推特权。 内推码&#xff1a;GTK3B6 内推码&#xff1a;GTK3B6 内推码&…

01背包笔记

01背包题目链接 题意&#xff1a;有一个容量为m的背包以及n个可以拿的物品&#xff0c;给出n个物品的体积和价值&#xff0c;要求输出可以拿的最大价值 思路&#xff1a;代表在前i件物品中拿取总体积不超过j的最大价值 由此可以分情况讨论状态转移 当j<v[i]时&#xff0c;说…

STM32(HAL)串口中断接收

目录 1、简介 2 基础配置 2.1.1 SYS配置 2.1.2 RCC配置 2.2 串口外设配置 2.3 项目生成 3、KEIL端程序整合 1、简介 本文对HAL串口中断函数进行介绍。 2 基础配置 2.1.1 SYS配置 2.1.2 RCC配置 2.2 串口外设配置 2.3 项目生成 3、KEIL端程序整合 首先在main.c文件中进行…

【Spring】Spring之循环依赖底层源码解析

什么是循环依赖 A依赖了B&#xff0c;B依赖了A。 示例&#xff1a; // A依赖了B class A{public B b; }// B依赖了A class B{public A a; }其实&#xff0c;循环依赖并不是问题&#xff0c;因为对象之间相互依赖是很正常的事情。示例&#xff1a; A a new A(); B b new B…

C5.0决策树建立个人信用风险评估模型

通过构建自动化的信用评分模型&#xff0c;以在线方式进行即时的信贷审批能够为银行节约很多人工成本。本案例&#xff0c;我们将使用C5.0决策树算法建立一个简单的个人信用风险评估模型。 导入类库 读取数据 #创建编码所用的数据字典 col_dicts{} #要编码的属性集 cols [che…

51单片机学习--LED点阵屏显示图形动画

为了通用性考虑&#xff0c;需要把用到的几个口用特殊位声明来重新命名&#xff0c;由于RCLK在头文件中已有定义&#xff0c;所以这里把P3^5声明成RCK吧。。这样的做法可以提高可读性 sbit RCK P3^5; //RCLK sbit SCK P3^6; //SRCLK sbit SER P3^4;接下来编写74HC595的输…

AI 绘画Stable Diffusion 研究(三)sd模型种类介绍及安装使用详解

本文使用工具&#xff0c;作者:秋葉aaaki 免责声明: 工具免费提供 无任何盈利目的 大家好&#xff0c;我是风雨无阻。 今天为大家带来的是 AI 绘画Stable Diffusion 研究&#xff08;三&#xff09;sd模型种类介绍及安装使用详解。 目前&#xff0c;AI 绘画Stable Diffusion的…

vue+neo4j(neo4j desktop安装和使用)

vueneo4j&#xff08;neo4j desktop安装和使用&#xff09; 本文目录 vueneo4j&#xff08;neo4j desktop安装和使用&#xff09;官网下载安装基本使用创建项目新增数据库连接数据库 使用cypher构建简单知识图谱创建节点创建关系删除节点及关系查询节点和关系 数据导出为json文…

SpringCloudAlibaba之Sentinel(一)流控篇

前言&#xff1a; 为什么使用Sentinel&#xff0c;这是一个高可用组件&#xff0c;为了使我们的微服务高可用而生 我们的服务会因为什么被打垮&#xff1f; 一&#xff0c;流量激增 缓存未预热&#xff0c;线程池被占满 &#xff0c;无法响应 二&#xff0c;被其他服务拖…

LeetCode--剑指Offer75(3)

目录 题目描述&#xff1a;剑指 Offer 20. 表示数值的字符串&#xff08;中等&#xff09;题目接口解题思路什么是有限状态自动机&#xff1f;如何使用&#xff1f; 代码 PS: 题目描述&#xff1a;剑指 Offer 20. 表示数值的字符串&#xff08;中等&#xff09; 请实现一个函数…

Windows7+内网, 安装高版本nodejs,使用vite+vue3+typescript开发项目

前言&#xff1a;vite只支持高版本的nodejs&#xff0c;而高版本的nodejs只支持windows8及以上&#xff0c;且vite还对浏览器版本有兼容问题。以下均为vite官网截图 1、安装好低版本的nodejs win7系统建议安装13.及以下&#xff0c;我的是12.12.0这个版本。nodejs低版本官网下载…

【前端】搭建Vue3框架

目录 一、搭建准备二、node.js安装1、下载并安装2、配置默认安装目录和缓存日志目录①、创建默认安装目录和缓存日志目录&#xff08;我的node.js目录在D盘&#xff0c;所以直接在node.js文件夹下创建&#xff09;②、执行命令&#xff0c;配置默认安装目录和缓存日志目录到刚才…

Java ThreadPoolExecutor,Callable,Future,FutureTask 详解

目 录 一、ThreadPoolExecutor类讲解 1、线程池状态 五种状态 2、ThreadPoolExecutor构造函数 2.1&#xff09;线程池工作原理 2.2&#xff09;KeepAliveTime 2.3&#xff09;workQueue 任务队列 2.4&#xff09;threadFactory 2.5&#xff09;handler 拒绝策略 3、常…

【JMeter】 使用Synchronizing Timer设置请求集合点,实现绝对并发

目录 布局设置说明 Number of Simulated Users to Group Timeout in milliseconds 使用时需要注意的点 集合点作用域 实际运行 资料获取方法 布局设置说明 参数说明&#xff1a; Number of Simulated Users to Group 每次释放的线程数量。如果设置为0&#xff0c;等同…