基于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函数里面使能即可。
在这里插入图片描述

	//不使用中断即输出固定占空比的PWM
	HAL_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代码我放在了开头,需要自取。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

屏幕取色器Mac版_苹果屏幕取色工具_屏幕取色器工具

Sip for Mac 是Mac系统平台上的一款老牌的颜色拾取工具&#xff0c;是设计师和前端开发工作者必不可少的屏幕取色软件&#xff0c;你只需要用鼠标点一下即可轻松地对屏幕上的任何颜色进行采样和编码&#xff0c;并将颜色数据自动存到剪切板&#xff0c;方便随时粘贴出来。 Sip…

第1章 什么是JavaScript

引言 JavaScript最早诞生的原因是希望表单验证可以在客户端得到解决。频繁通过服务端的请求来验证表单缓慢的网速让页面每次刷新都考验着人们的耐心。 如今的js不再局限简单的表单验证&#xff0c;能够实现复杂的计算与交互&#xff0c;包括闭包、匿名&#xff08;lambda&…

学习笔记|简单分享一下自建Gravatar镜像

目录 前言 Gravatar 使用 思路 操作 步骤一&#xff1a;注册或登录华为云 步骤二&#xff1a;创建委托账号 步骤三&#xff1a;创建OBS桶 步骤四&#xff1a;数据回源配置 步骤五&#xff1a;配置生命周期规则 步骤六&#xff1a;绑定自定义域名 步骤七&#xff1a…

Cocos Creator的 Cannot read property ‘applyForce‘ of undefined报错

序&#xff1a; 1、博主是看了这个教程操作的时候出的bug>游戏开发 | 17节课学会如何用Cocos Creator制作3D跑酷游戏 | P9 代码控制对象移动_哔哩哔哩_bilibili 2、其实问题不是出在代码上&#xff0c;但是发现物体就是不平移 3、node全栈的资料》node全栈框架 正文…

django使用mysql数据库

Django开 发操作数据库比使用pymysql操作更简单&#xff0c;内部提供了ORM框架。 下面是pymysql 和orm操作数据库的示意图&#xff0c;pymysql就是mysql的驱动&#xff0c;代码直接操作pymysql ,需要自己写增删改查的语句 django 就是也可以使用pymysql、mysqlclient作为驱动&a…

python#django数据库一对一/一对多/多对多

一对一OneToOneField 用户和用户信息 搭建 # 一对一 class TestUser(models.Model): usernamemodels.CharField(max_length32) password models.CharField(max_length32) class TestInfo(models.Model): mick_namemodels.CharField(max_length32) usermode…

CMake:检测python解释器和python库

CMake:检测python解释器和python库 导言检测python解释器CMakeLists.txt输出附录 检测python库项目结构CMakeLists.txt相关源码附录 导言 python是一种非常流行的语言。许多项目用python编写的工具&#xff0c;从而将主程序和库打包在一起&#xff0c;或者在配置或构建过程中使…

【暑期每日一练】 day15

目录 选择题&#xff08;1&#xff09;解析&#xff1a; &#xff08;2&#xff09;解析&#xff1a; &#xff08;3&#xff09;解析&#xff1a; &#xff08;4&#xff09;解析&#xff1a; &#xff08;5&#xff09;解析&#xff1a; 编程题题一描述输入描述输出描述 示例…

Android 9-- 源码角度: Home键的监听和拦截

在做应用层APP需求的过程中&#xff0c;HOME键的监听&#xff0c;Back键的监听&#xff0c;这都是很常见的问题&#xff0c;那你有试过&#xff0c;去拦截HOME键的事件吗&#xff0c;有去了解过如何处理吗&#xff0c;流程如何 首先大家应该先了解一种情况&#xff0c;就是Andr…

Red Hat 安装JDK与IntelliJ IDEA

目录 前言 Red Hat 安装 JDK 1、更新软件包列表 2、安装OpenJDK 3、验证安装 Red Hat 安装IntelliJ IDEA 1、下载 IntelliJ IDEA 2、解压缩 IntelliJ IDEA 安装包 3、移动 IntelliJ IDEA 到安装目录 4、启动 IntelliJ IDEA 前言 YUM是基于Red Hat的Linux发行版的一个…

flask-session、数据库连接池

flask 自带session---》以cookie的形式放到了浏览器中---》加密 真正的session&#xff0c;是在服务端存储 -django中存在djangosession表中 -flask中&#xff0c;使用第三方&#xff0c;保存在---》redis中---》flask-session 使用步骤 pip install flask-session …

Stable Diffusion 使用教程

环境说明&#xff1a; stable diffusion version: v1.5.1python: 3.10.6torch: 2.0.1cu118xformers: N/Agradio: 3.32.0 1. 下载 webui 下载地址&#xff1a; GitHub stable-diffusion-webui 下载 根据自己的情况去下载&#xff1a; 最好是 N 卡&#xff1a;&#xff08;我的…

vscode无法连接远程服务器的可能原因:远程服务器磁盘爆了

vscode输入密码后一直等待&#xff0c;无法进入远程服务器终端&#xff1a; 同时Remote-SSH输出包含以下内容 在日志中的以下几个部分&#xff1a; [17:15:05.529] > wget download failed 这表明VS Code尝试在远程服务器上下载VS Code服务器时失败了。> Cannot write…

小孩学python课程需要多久,儿童学python哪个机构好

本篇文章给大家谈谈小孩学python课程需要多久&#xff0c;以及儿童学python语言能做什么&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 学习儿童python编程越来越受欢迎&#xff0c;原因有很多&#xff0c;对于孩子来说&#xff0c;Python是一种很好的编程语…

Linux|ubuntu下运行python

参考&#xff1a;ubuntu系统下切换python版本的方法 文章目录 python版本问题查看ubuntu下的所有python版本通过apt-get install可以安装不同版本python查看python版本号更新update-alternatives替代列表查看update-alternatives下的python版本切换python版本删除python版本 p…

汽车智能化再掀新热潮!「中央计算架构」进入规模量产周期

中央计算区域控制的新一代整车电子架构&#xff0c;已经成为车企继电动化、智能化&#xff08;功能上车&#xff09;之后&#xff0c;新一轮竞争的焦点。 如果说智能化的1.0阶段&#xff0c;是智能驾驶智能座舱的争夺战&#xff1b;那么&#xff0c;即将进入的2.0阶段&#xff…

微服务——操作索引库+文档操作+RestClient操作索引库和文档(java程序)

索引库操作 mapping属性 mapping是对文档的约束&#xff0c;常见约束属性包括: 创建索引库 #创建索引库 PUT /heima {"mappings": {"properties": {"info":{"type": "text","analyzer": "ik_smart"},…

机器学习笔记之优化算法(十)梯度下降法铺垫:总体介绍

机器学习笔记之优化算法——梯度下降法铺垫&#xff1a;总体介绍 引言回顾&#xff1a;线搜索方法线搜索方法的方向 P k \mathcal P_k Pk​线搜索方法的步长 α k \alpha_k αk​ 梯度下降方法整体介绍 引言 从本节开始&#xff0c;将介绍梯度下降法 ( Gradient Descent,GD ) …

Appium+Python3环境搭建,其实超简单!

appium可以说是做app最火的一个自动化框架&#xff0c;它的主要优势是支持android和ios&#xff0c;另外脚本语言也是支持java和Python。略懂Python&#xff0c;所以接下来的教程是appiumpython&#xff0c;自己搭建环境的时候&#xff0c;按照某些博客安装遇到各种奇葩问题&am…

Python爬虫——爬虫时如何知道是否代理ip伪装成功?

前言 在进行爬虫时&#xff0c;我们可能需要使用代理IP来伪装自己的身份&#xff0c;以避免被网站封禁。如何判断代理IP是否伪装成功呢&#xff1f;本篇文章将围绕这个问题展开讲解&#xff0c;同时提供Python代码示例。 1. 确认代理IP地址 首先&#xff0c;我们需要确认代理…