STM32F4X 定时器PWM

news2025/1/12 10:55:51

STM32F4X 定时器PWM

  • 什么是PWM
  • STM32F4X PWM使用
    • GPIO引脚复用
    • STM32F4X PWM配置参数
      • 定时器PWM输出通道
      • 定时器PWM输出模式
      • 定时器PWM有效电平
      • 定时器PWM工作过程
      • 定时器PWM频率计算
    • STM32F4X PWM配置步骤
    • STM32F4X PWM配置函数

上节说到了定时器的定时功能,这节说一下定时器跟GPIO结合,输出PWM波形的功能。

什么是PWM

PWM是Pulse Width Modulation 的缩写,也叫脉冲宽度调节,PWM被广泛应用在产品中,比如常用的有LED灯调节、电机脉冲调节等。PWM有以下几个参数需要了解,分别是周期、高电平持续时间、低电平持续时间和占空比。下面就来简单了解一下PWM的概念。
在这里插入图片描述
T:PWM周期,周期是指高低电平的持续时间为一个周期。
T1:高电平时间
T2:低电平时间
占空比:占空比为 (高电平时间 / 周期) * 100%
比如上图中,T为1ms,T1为600us,T2为400us,那么占空比就为 600 / (1 * 1000) * 100% = 60%

STM32F4X PWM使用

GPIO引脚复用

前面的章节讲过,STM32F4X的GPIO除了用作普通的输入输出接口之外,还可以复用成其他的功能。本节就将GPIO接口复用成定时器模式,具体可以在STM32F4的数据手册中找到GPIO的复用表。下面就以PF9为例,下面的表格可以看到,STM32F4X的PF9引脚可以复用成定时器14的通道1,所以后面的例程就用定时器14的通道1来输出PWM波形。
在这里插入图片描述

STM32F4X PWM配置参数

定时器PWM输出通道

在STM32F4X中,每个定时器都会有几路PWM的输出,具体是使用哪一路的PWM要根据GPIO的复用表格进行确定,像PF9在表格中就复用成了TIM14_CH1,也就是定时器的通道1,在后面的编程中要注意通道不能用错。

定时器PWM输出模式

在定时器的PWM模式中,有两种输出模式,分别是PWM1和PWM2,这两种模式有以下区别。
在这里插入图片描述
TIMx_CNT表示定时器当前计数器的值
TIMx_CCRn表示捕获/比较寄存器的值

定时器PWM有效电平

有效电平通常要跟上面所说的PWM模式结合来使用,在STM32F4X中的PWM有效电平可以配置成高电平有效或者低电平有效。

定时器PWM工作过程

下面来简单讲一下STM32F4X的PWM工作过程。以PWM模式2、定时器向上计数模式和有效电平为高电平的情况来进行讲解。如下图所示

在这里插入图片描述
CNT代表定时器当前计数值
ARR为重装载寄存器值
CCRx为捕获/比较寄存器值
通过定时器PWM输出模式的表格可以知道,在向上计数模式和PWM2模式下,当CNT<CCR时,电平无效,而我们的有效电平设了高电平有效,也就是CNT<CCR时,输出低电平。反之,当CNT>CCR时,电平有效,输出高电平。也就是上图会输出如下的PWM波形。
在这里插入图片描述

定时器PWM频率计算

在向上计数模式、PWM1模式和高电平有效的条件下。假设定时器时钟源为84MHZ,定时器分频系数为83(PSC),重装载值为5999(ARR),输出比较寄存器CCR为2000,通过下面公式可以算出定时器的中断频率。
Tout:定时器溢出值
Tclk:84MHZ
psc:83
arr:5999
Tout = (1 / (Tclk / (psc + 1))) * (arr + 1)
Tout等于1us中断一次
就可以算出PWM的周期为6000 * 1us = 6000us = 6ms。
而高电平的时间就为CCR * 1us = 2000us = 2ms
占空比就为2 / 6 * 100% = 33%

STM32F4X PWM配置步骤

  • 使能GPIO时钟和定时器时钟
  • 配置GPIO引脚为定时器模式
  • 配置定时器工作频率
  • 配置定时器PWM模式
  • 使能定时器
  • 如果需要可以修改PWM占空比
    经过上面的步骤就可以使用PWM功能了。

STM32F4X PWM配置函数

/*
定时器初始化函数
TIMx:定时器索引
TIM_TimeBaseInitStruct:定时器初始化结构体
*/
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)

/*
定时器通道初始化函数
TIMx:定时器索引
TIM_OCInitStruct:比较输出初始化结构体
*/
void TIM_OCXInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)

/*
定时器比较初始化寄存器设置函数
TIMx:定时器索引
Comparex:CCR值
*/
void TIM_SetComparex(TIM_TypeDef* TIMx, uint32_t Comparex)

PWM程序例程


void bsp_pwm_init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef TIM_OCInitStruct;
	GPIO_InitTypeDef GPIO_InitStruct;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE); // 使能定时器14时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); 	//使能PORTF时钟	
	
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;           //GPIOF9
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;        //复用功能
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
	GPIO_Init(GPIOF,&GPIO_InitStruct);              //初始化PF9
	
	GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); // PF9复用成TIM14
	
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; 
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
	TIM_TimeBaseInitStruct.TIM_Period = 999; // 重装值为1000 1ms中断一次
	TIM_TimeBaseInitStruct.TIM_Prescaler = 83; // 预分配值为84 即84000000/84 = 1MHZ 1us计一次书
	TIM_TimeBaseInit(TIM14,&TIM_TimeBaseInitStruct); // 初始化定时器14
	
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; // 有效电平为高电平
	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; // 使能比较输出
	TIM_OCInitStruct.TIM_Pulse = 300; // CCR值为300
	TIM_OC1Init(TIM14,&TIM_OCInitStruct);
	
	TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);  //使能TIM14在CCR1上的预装载寄存器
 
	TIM_ARRPreloadConfig(TIM14,ENABLE);//ARPE使能 
	TIM_Cmd(TIM14,ENABLE); // 使能定时器14
	
}


int main(void)
{
	int dir,led0pwmval = 0;
	NVIC_PriorityGroupConfig(2);
	system_tick_init();
	
	bsp_usart_init(115200);
	bsp_pwm_init();

  while(1){
		delay_ms(1);
		if(dir)
			led0pwmval++;//dir==1 led0pwmval递增
		else 
			led0pwmval--;	//dir==0 led0pwmval递减 
 		if(led0pwmval>1000)
			dir=0;//led0pwmval到达1000后,方向为递减
		if(led0pwmval==0)
			dir=1;	//led0pwmval递减到0后,方向改为递增
 
		TIM_SetCompare1(TIM14,led0pwmval);	//修改比较值,修改占空比
	  
	}
  
}

在这里插入图片描述

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

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

相关文章

10种最流行的3D模型文件格式及转换方法

3D 文件格式用于存储有关 3D 模型的信息。 你可能听说过一些最流行的格式&#xff0c;包括 STL、OBJ、FBX 和 DAE。 它们广泛应用于从视频游戏动画到工业增材制造的各种应用中。 在本文中&#xff0c;我们将考虑为什么有这么多不同的格式&#xff0c;探讨 3D 文件格式存储的四…

已解决W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library ‘c

已解决W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library ‘cudart64_110.dll’; dlerror: cudart64_110.dll not found I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not ha…

C++ 二叉搜索树的概念特性

1. 二叉搜索树 1.1 二叉搜索树概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树 &#xff0c;或者是具有以下性质的二叉树 : 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;则右子树上所有节点的值都大…

华为云部署JDK环境

一、确定系统内核 在下载jdk之前要先确定自己的内核是什么版本&#xff0c;因为我选的云服务器是CentOS7&#xff0c;所以一定是Linux_86_64版本。 若不确定可以在命令行中输入“uname -a”来查看系统内核。 二、下载JDK 到官网下载对应统信系统版本的jdk安装包 jdk官网&…

Java进阶(5)——创建多线程的方法extends Thread和implements Runnable的对比 线程池及常用的线程池

目录 引出创建多线程的方法Thread类创建多线程Runnable接口创建多线程Thread类的常用方法两者的对比 线程池是啥&#xff1f;为啥用&#xff1f;结合案例理解常用的线程池继承Runnable接口的工人实体类newSingleThreadExecutor&#xff08;单线程&#xff09;newFixedThreadPoo…

Simulink仿真模块 - Clock

Clock&#xff1a;显示并提供仿真时间 库&#xff1a; Simulink / Sources 模型为&#xff1a; 说明 Clock 模块在每个仿真时间步输出当前仿真时间。此模块对需要仿真时间的其他模块非常有用。 当在离散系统中需要当前时间时&#xff0c;请使用Digital Clock模块。 实例 模块…

利用python批量掩膜提取遥感图像

&#xff08;1&#xff09; 前言 遥感影像的提取和分析在地理信息系统、环境监测、农业、城市规划等领域具有重要的应用价值。按掩膜提取遥感影像是一种常用的方法&#xff0c;它可以通过定义掩膜来选择感兴趣的区域&#xff0c;并排除其他干扰因素。 按掩膜提取遥感影像的方…

ssm网上服装销售系统源码和论文

ssm网上服装销售系统047 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 目前互联网上的网上销售系统每天以惊人的速度增加&#xff0c;网上购物越来越成为现代年轻人的首选&#xff0c;足不出门便能选购好自己…

H5商城公众号商城系统源码 积分兑换商城系统独立后台

网购商城系统源码 积分兑换商城系统源码 独立后台附教程 测试环境&#xff1a;NginxPHP7.0MySQL5.6thinkphp伪静态

胖小酱之广告

广告是一种宣传手段&#xff0c;通过一定形式的媒体&#xff0c;向公众传递信息的方式。广告可以分为广义和狭义两种&#xff0c;其中广义广告是指不以营利为目的的广告&#xff0c;如政府公告、社会团体声明等&#xff1b;狭义广告则是指以营利为目的的广告&#xff0c;通常是…

【JAVA基础】 IO详解

【JAVA基础】 IO详解 文章目录 【JAVA基础】 IO详解一、概述二、IO流的作用三、IO流的使用场景四、IO流的分类4.1 传输数据的单位分&#xff1a;4.2 数据传输的方向分&#xff1a;4.3 流的角色的不同分&#xff1a; 五、IO流体系六、字节输入流InputStream七、字节输出流 Outpu…

Python 从入门到实践第3版(中文版)正式版+编制版+电子版

Python编程&#xff1a;从入门到实践&#xff08;第3版&#xff09; ([美] 埃里克 • 马瑟斯&#xff08;Eric Matthes&#xff09;) 2023 (Z-Library)

【算法日志】动态规划刷题:01背包问题(day36)

代码随想录刷题60Day 前言 今天主要讨论背包问题中的01背包问题&#xff0c;这类问题的难点在于怎样对问题进行数学建模。一旦思考好问题的解决方式&#xff0c;剩下的步骤就比较简单了。 分割等和子集 本题可采用暴力回溯&#xff0c;但复杂度比较高&#xff0c;所以采取动态…

解决Win10运行软件程序提示【管理员已阻止你运行此应用】

一、问题描述 在Win10系统打开软件&#xff0c;弹窗提示【管理员已阻止你运行此应用】&#xff0c;如下图所示&#xff1a; 二、问题分析 是由于Windows系统的安全策略设置影响&#xff0c;保护你的电脑不被恶意程序破坏&#xff1b;只用修改系统的安全策略即可。 三、解决办法…

多目标优化算法知识点梳理

EA进化算法 MOEA多目标进化算法 1.MOEA的分类 1.1 按不同的进化机制分类 基于分解的MOEA&#xff1a;是比较早起所使用的方法&#xff1a;聚集函数法。将被优化的所有子目标组合或聚集为单个目标&#xff0c;从而将多目标优化问题转换为单目标优化问题。 基于支配关系的MOE…

ACME协议申请泛域名证书

ACME协议申请泛域名证书 注册域名 namecheap迁移DNS到cloudflare创建API令牌 区域选择域名生成证书安装证书参考 注册域名 namecheap 迁移DNS到cloudflare 创建API令牌 区域选择域名 复制此令牌&#xff0c;令牌只显示一次。 生成证书 export CF_Token"API令牌"a…

从零实现深度学习框架——Transformer从菜鸟到高手(二)

引言 &#x1f4a1;本文为&#x1f517;[从零实现深度学习框架]系列文章内部限免文章&#xff0c;更多限免文章见 &#x1f517;专栏目录。 本着“凡我不能创造的&#xff0c;我就不能理解”的思想&#xff0c;系列文章会基于纯Python和NumPy从零创建自己的类PyTorch深度学习框…

C++信息学奥赛2046:【例5.15】替换字母

这段代码的功能是对输入的字符串进行处理&#xff0c;将字符串中的字符 a 替换为字符 b 后输出结果。 #include<bits/stdc.h> using namespace std; int main() {string s; // 定义字符串变量s&#xff0c;用来存储输入的字符串char a, b; // 定义字符变量a和b&#xff…

港科夜闻|香港科大将与世界经济论坛合作举办大中华区首个全球青年领袖论坛领导力发展课程,与全球青年领袖共同探讨人工智能...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、​香港科大将与世界经济论坛合作举办大中华区首个"全球青年领袖论坛领导力发展课程",与全球青年领袖共同探讨人工智能。香港科大下月将与世界经济论坛合作&#xff0c;接待40位来自包括欧洲、拉丁美洲、非洲和…

采用typescript编写,实现ofd前端预览、验章

前言 浏览器内核已支持pdf文件的渲染&#xff0c;这极大的方便了pdf文件的阅读和推广。ofd文件作为国产板式标准&#xff0c;急需一套在浏览器中渲染方案。 本人研究ofd多年&#xff0c;分别采用qt、c# 开发了ofd阅读器。本人非前端开发人员&#xff0c;对js、typescript并不熟…