STM32入门之通用定时器PWM

一、通用定时器简介

STM32通用定时器由一个通过可编程预分频器驱动的16位自动重装载计数器组成,适用于多种应用场景,包括测量输入信号的脉冲长度(利用输入捕获功能)和生成输出波形(使用输出比较及PWM功能)。借助于定时器预分频器以及RCC时钟控制器提供的预分频能力,用户可以灵活调整脉冲长度和波形周期,范围可从几微秒至几毫秒不等。每个通用定时器都是完全独立的,不共享任何资源,这保证了它们可以在互不影响的情况下单独运行,同时也支持同步操作,以满足复杂的实时控制需求。

通用TIMx (TIM2、TIM3、TIM4和TIM5)定时器功能包括:

  • 16位向上、向下、向上/向下自动装载计数器
  • 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65536之间的任意数值
  • 4个独立通道:
  • 输入捕获
  • 输出比较
  • PWM生成(边缘或中间对齐模式)
  • 单脉冲模式输出
  • 使用外部信号控制定时器和定时器互连的同步电路
  • 如下事件发生时产生中断/DMA:
  • 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
  • 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
  • 输入捕获
  • 输出比较
  • 支持针对定位的增量(正交)编码器和霍尔传感器电路
  • 触发输入作为外部时钟或者按周期的电流管理

二、通用定时器内部结构

通用定时器的内部结构相较于基本定时器而言复杂得多,主要由以下几个关键部分组成:时基单元、时钟发生器、输入捕获以及输出比较等。

1. 时钟源

通用定时器提供了四种不同的时钟来源选项,具体选择可通过配置TIMx_SMCR寄存器的相关位来实现:

(1)内部时钟(CK_INT):这是最常见的时钟源选择,适用于大多数应用场景。

(2)外部时钟模式1:使用外部输入引脚TIx(x=1,2,3,4)作为时钟源,允许定时器根据外部信号进行计数。

(3)外部时钟模式2:通过外部触发输入ETR提供时钟信号,进一步扩展了定时器的应用范围。

(4)内部触发输入(ITRx,x=0,1,2,3):利用其他定时器或系统内部产生的触发信号作为时钟源。

在典型配置中,我们通常选择内部时钟(CK_INT)作为通用定时器的时钟来源,并且由于APB1的时钟分频系数不为1,通用定时器的时钟频率是APB1时钟的两倍,即72MHz。

2. 控制器

通用定时器的控制器部分集成了触发控制器、从模式控制器以及编码器接口,以支持广泛的应用需求。

触发控制器负责生成触发信号,可用于驱动片内外设的操作,如为其他定时器提供时钟或触发DAC和ADC转换,从而增强系统内不同模块间的同步与协调能力。

从模式控制器则管理计数器的各种操作状态,包括复位、启动、递增或递减计数,使得定时器能够适应复杂的计数模式和同步操作要求,满足多样化的实时控制需求。此外,专门设计的编码器接口用于处理来自旋转编码器的输入信号,通过准确解码位置信息调整计数器值,适用于需要精确位置反馈的应用场景。

3. 时基单元

通用定时器的时基单元由三个核心寄存器组成:计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)和自动重装载寄存器(TIMx_ARR)。在高级定时器中,还额外包含一个重复计数寄存器(TIMx_RCR),这一特性在通用和基本定时器中并不存在。

在时基单元内,预分频器寄存器(TIMx_PSC)用于对计数器时钟频率进行分频调整。通过设置寄存器内的相应位,可以将分频系数设定在1到65536之间,从而灵活控制计数器的工作频率。由于从模式控制寄存器具备缓冲功能,预分频器支持实时更改,新的分频比将在下一个更新事件发生时生效。

此外,时基单元中的计数器寄存器(TIMx_CNT)支持多种计数方式:

(1)向上计数

在向上(递增)计数模式下,计数器从0开始计数,每当接收到一个CK_CNT脉冲时,计数器的值增加1,直至达到自动重载寄存器(TIMx_ARR)中设定的值。此时,计数器会触发一次上溢事件,并重新从0开始计数。

(2)向下计数

在向下(递减)计数模式下,计数器从自动重载寄存器(TIMx_ARR)中设定的值开始递减计数,每接收到一个CK_CNT脉冲时,计数器的值减少1,直至计数至0。此时,计数器触发一次下溢事件,并重新从自动重载值开始新一轮计数。

(3)中央对齐计数

在中心对齐模式下,计数器的操作分为两个阶段:首先从0开始递增计数至自动重载寄存器(TIMx_ARR)中设定的值减1,此时生成计数器上溢事件;然后从自动重载值开始递减计数至1,并生成计数器下溢事件。

在时基单元中还有一个自动重载寄存器(TIMx_ARR),它用于存储与计数器(TIMx_CNT)进行比较的目标值。

4. 输入捕获单元

输入捕获单元主要由以下几部分组成:输入通道、输入滤波器和边沿检测器、输入捕获通道、预分频器以及捕获/比较寄存器。

在输入捕获模式下,当ICx输入信号检测到设定的跳变沿时,计数器的当前值会被锁存到捕获/比较寄存器(TIMx_CCRx)。每次捕获事件发生时,相应的捕获标志位CCxIF(位于TIMx_SR寄存器中)被置1,并可触发中断或DMA请求。

ICx输入信号经过预分频器处理,根据TIMx_CCMRx寄存器中的ICxPSC位设置预分频系数,决定每多少个事件进行一次捕获。若需捕获每个边沿,则预分频系数应设为1。首次捕获时,计数器CNT的值被锁存到CCR寄存器并产生中断,CCxIF标志被置位;若CCR已有值且CCxIF已置1,则发生第二次捕获时,捕获溢出标志位CCxOF会被置位,该标志只能通过软件写0清零。

5. 输出比较通道

通用定时器通常配备有多个输出通道(TIMx_CH1/2/3/4),这些通道对应于STM32微控制器上的物理引脚。每个输出通道可以独立配置为不同的功能,如输出比较、PWM生成等。

输出比较单元与输入捕获单元共享捕获/比较寄存器(TIMx_CCRx)。然而,在输出比较模式下,这些寄存器主要发挥其比较功能的作用。当计数器CNT的值与比较寄存器CCR的值相等时,输出参考信号OCxREF的极性会发生改变,并且会产生一个比较中断CCxI。此时,相应的标志位CCxIF(位于SR寄存器中)会被置位。

在发生比较匹配事件后,OCxREF信号经过一系列控制处理,最终转换为实际的输出信号OC1/2/3/4。这些输出信号会通过对应的管脚TIMx_CH1/2/3/4输出到外部设备。

三、PWM简介

什么是PWM?

PWM是 Pulse Width Modulation 的缩写,中文意思就是脉冲宽度调制,简称脉宽度调制,其核心思想是通过快速开关数字信号并改变其开启时间(脉宽)的比例来控制输送到负载的平均功率或电压,即控制占空比。

它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,其控制简单、灵活和动态响应好等优点而成为电力电子技术最广泛应用的控制方式,其应用领域包括测量,通信,功率控制与变换,电动机控制、伺服控制、调光、开关电源,甚至某些音频放大器,因此学习PWM具有十分重要的现实意义。

  • PWM 信号是一个周期性的方波(高电平-低电平交替)。
  • 占空比 是一个周期内高电平(脉冲开启)时间占整个周期时间的百分比。
  • 公式:占空比 = (脉冲开启时间 / 周期时间) × 100%
  • 例如:一个周期为 10ms 的 PWM 信号,如果高电平持续 3ms,则占空比为 30%;如果高电平持续 7ms,则占空比为 70%。

与模拟控制的区别

  • 传统的模拟控制(如使用可变电阻)是通过连续地改变电压或电流的大小来控制负载。
  • PWM 控制是通过改变数字脉冲的宽度比例来达到类似的连续控制效果。它是数字式的开关控制,而非连续的模拟调节。
  • PWM 控制本质上改变的是负载两端的 平均电压 和流经负载的 平均电流,而不是瞬时电压或电流的峰值

通用定时器的PWM模式

PWM(脉冲宽度调制)模式是输出比较模式的一种特例,专门用于生成具有特定频率和占空比的PWM波形。它可以配置为PWM1模式或PWM2模式,适用于电机控制、LED亮度调节等多种应用。

PWM1模式:当计数器CNT的值小于比较寄存器CCR的值时,输出高电平;反之,输出低电平。这使得输出信号的占空比由CCR值决定。

PWM2模式:与PWM1模式相反,当计数器CNT的值小于比较寄存器CCR的值时,输出低电平;反之,输出高电平。

通过调整计数器的自动重装载值(TIMx_ARR)和比较寄存器(TIMx_CCRx)的值,可以精确控制PWM信号的周期和占空比。

四、代码实现定时器输出PWM脉冲

本实验使用通用定时器TIM3的通道1来输出PWM脉冲,TIM3的输出通道1是映射在GPIO引脚PA6上,并在PA6引脚接一个LED灯。我们通过控制PWM占空比,实现呼吸灯的效果。(灯的亮度由亮到暗,再由暗到亮)

1.配置步骤

  • 使能外设TIM3、GPIOA时钟
  • 初始GPIO
  • 初始化定时器,配置定时器的时基单元和输出通道部分
  • 使能定时器
  • 使能输出比较预装载寄存器
  • 使能自动重装载预装载寄存器
  • 设置比较寄存器的值

2.代码实现

编写tim_drv.c文件

#include "tim_drv.h"/*********************************************************************************** @brief :  定时器PWM输出配置函数*                * @param :  arr 自动重装载值* @param :  psc 预分频系数* @retval  : 无
**********************************************************************************/
void PWM_Config(uint16_t arr, uint16_t psc)
{//开启外设GPIO时钟 复用时钟AFIO  定时器TIM3时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//GPIO初始化GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;      //引脚6GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//速率GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化定时器TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  //时钟分割TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式TIM_TimeBaseInitStruct.TIM_Period = arr;         //自动重装载值TIM_TimeBaseInitStruct.TIM_Prescaler = psc;      //预分频系数TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);//输出比较通道参数初始化TIM_OCInitTypeDef TIM_OCInitStruct;TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; //PWM1模式TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_Low; //有效电平为低电平TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;  //输出使能TIM_OCInitStruct.TIM_Pulse = 0; //初始占空比为0(整个计数周期PWM波形为高电平)TIM_OC1Init(TIM3,&TIM_OCInitStruct);//使能输出比较预装载寄存器TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能自动重装载预装载寄存器TIM_ARRPreloadConfig(TIM3,ENABLE);//使能定时器TIM_Cmd(TIM3,ENABLE);
}

编写tim_drv.h文件

#ifndef __TIM_DRV_H__
#define __TIM_DRV_H__//头文件包含
#include "stm32f10x.h"//函数声明
void PWM_Config(uint16_t arr, uint16_t psc);#endif

编写main.c文件

#include "led_drv.h"
#include "systick.h"
#include "tim_drv.h"int main(void)
{uint8_t dir=0;uint16_t ccr = 0;SysTick_Init(72);//初始化systickPWM_Config(100-1,720-1);//初始化LEDwhile (1){if(!dir){ccr++;if(ccr >= 500)dir = 1;}else{ccr--;if(ccr <= 0)dir =0;}TIM_SetCompare1(TIM3,ccr);delay_ms(5);}
}

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

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

相关文章

第十八节 MATLAB for循环

MATLAB中 for 循环是一个重复的控制结构&#xff0c;可以有效地写一个循环&#xff0c;只是执行的次数是特定的。MATLAB for 循环语法:MATLAB中的 for循环的语法如下&#xff1a;for index values<program statements>... endfor 循环的值有下述三种形式之一&#xff1a…

嵌入式硬件篇---zigbee无线串口通信问题解决方法

针对 ZigBee 无线串口通信中接收异常的问题&#xff0c;需结合其射频特性、网络机制、硬件配置等多维度原因&#xff0c;采取针对性解决措施。以下从具体场景出发&#xff0c;提供可落地的解决方法&#xff1a;一、解决射频层干扰与信号衰减问题射频层是无线通信的基础&#xf…

移动高清盒子6PRO-河南创维E900V22D-晶晨S905L3B-4+16G-安卓9-线刷固件包

移动高清盒子6PRO-河南创维E900V22D-晶晨S905L3B-416G-安卓9-线刷固件包线刷方法&#xff1a;1、准备好一根双公头USB线刷刷机线&#xff0c;长度30-50CM长度最佳&#xff0c;同时准备一台电脑&#xff1b;2、电脑上安装好刷机工具Amlogic USB Burning Tool 软件 →打开软件 →…

台式电脑有多个风扇开机只有部分转动的原因

一、风扇未连接或连接松动这是最常见的原因之一&#xff0c;台式机风扇通常需要通过线材与主板或电源连接&#xff1a;主板接口问题&#xff1a;CPU 风扇、机箱风扇等多连接到主板的风扇接口&#xff08;如 CPU_FAN、SYS_FAN&#xff09;&#xff0c;若线材未插紧、插错接口&am…

【测试报告】思绪网(Java+Selenium+Jmeter自动化测试)

一、项目简介思绪网作为一种在线交流平台&#xff0c;支持用户在平台下发布文章&#xff0c;并进行讨论。主要由登录页面&#xff0c;论坛页面&#xff0c;帖子编辑页&#xff0c;帖子详情页等页面组成。二、项目功能1.登录页面&#xff1a;输入正确的账号密码进行登录,跳转博客…

Nestjs框架: 基于Mongodb的多租户功能集成和优化

概述 基于前文&#xff0c;我们知道如何集成多租户的相关功能了, 现在我们继续集成Monodb的多租户形式需要注意的是&#xff0c;MongoDB 在 NestJS 中的使用过程中存在一些“坑点”如果按照默认方式集成&#xff0c;会发现连接数在不断增长&#xff0c;即使我们请求的是相同的数…

如何利用机器学习分析筛选生物标记物

在生物信息学中&#xff0c;Lasso回归、随机森林&#xff08;Random Forest&#xff09;和XGBoost因其各自的特性和优势&#xff0c;被广泛应用于基因组学、蛋白质组学、药物发现和疾病机制研究等领域。 Lasso回归 癌症亚型分类&#xff1a;从TCGA数据中筛选驱动基因&#xf…

计算机网络(基础篇)

TCP/IP 网络模型 应用层&#xff08;Application Layer&#xff09; 应用层只需要专注于为用户提供应用功能&#xff0c;比如 HTTP、FTP、Telnet、DNS、SMTP等。应用层是工作在操作系统中的用户态&#xff0c;传输层及以下则工作在内核态。传输层&#xff08;Transport Layer&a…

全面解析 CSS Flex 布局:从入门到精通的所有属性详解

1. Flex 容器属性 通过 display: flex 或 display: inline-flex 将元素设置为 Flex 容器。以下是所有容器属性。 1.1 display: flex | inline-flex 作用&#xff1a;定义一个 Flex 容器。可选值&#xff1a; flex&#xff1a;块级容器&#xff0c;占据整行。inline-flex&#x…

数据结构:对角矩阵(Diagonal Matrix)

目录 矩阵的传统表示&#xff1a;二维数组 &#x1f50d; 真正有用的数据是哪些&#xff1f; 从二维数组转为一维数组 用 C 类实现对角矩阵 1. 对角矩阵真正需要存什么&#xff1f; 2. 对角矩阵允许哪些行为&#xff1f; 3. 为什么要动态分配数组&#xff1f; 接下来推…

Leetcode_349.两个数组的交集

这道题的意思很明确&#xff0c;就是让寻找两个数组中的共同元素&#xff0c;并去重&#xff0c;由此可以联想到哈希表的特性&#xff0c;注意到题目给的数据范围&#xff0c;在1000以内&#xff0c;所以本题可以使用 STL 的库函数&#xff0c;也可以使用数组进行模拟。 本题要…

STM32——寄存器映射

总 &#xff1a;STM32——HAL库总结-CSDN博客 芯片资料&#xff1a; STM32F1系列参考手册-V10&#xff08;中&#xff09; STM32F103ZET6(English) 一、寄存器基础 1.1 简介 单片机内部的控制机构。 像空气开关控制电路一样的原理&#xff0c;打开关闭某个开关&#xff0…

Java响应式编程

Java 响应式编程是一种基于异步数据流处理的编程范式&#xff0c;它强调数据流的声明式构建和传播变化的自动响应。Java 9 引入的Flow API为响应式编程提供了标准接口&#xff0c;而 Reactor 和 RxJava 等第三方库则提供了更丰富的操作符和工具。核心概念Publisher&#xff08;…

【重学数据结构】二叉搜索树 Binary Search Tree

目录 二叉搜索树的数据结构 手写实现二叉搜索树 树节点定义 插入节点 源码 流程图 二叉树插入步骤图解 第一步: 插入 20 第二步: 插入 10 第三步: 插入 30 第四步: 插入 5 查找节点 源码 场景一: 查找成功 (search for 25) 第一步: 从根节点开始 第二步:…

四、计算机组成原理——第1章:计算机系统概述

目录 1.1计算机发展历程 1.1.1计算机硬件的发展 1.计算机的四代变化 2.计算机元件的更新换代 1.1.2计算机软件的发展 1.2计算机系统层次结构 1.2.1计算机系统的组成 1.2.2计算机硬件 1.冯诺依曼机基本思想 2.计算机的功能部件 (1)输入设备 (2)输出设备 (3)存储器 (4)运算器 (5)…

flutter TextField 失去焦点事件

在 Flutter 中&#xff0c;处理 TextField 的失去焦点事件&#xff08;即失去焦点时触发的操作&#xff09;通常有两种常用方式&#xff1a;使用 FocusNode 或 onEditingComplete 回调。以下是具体实现&#xff1a; import package:flutter/material.dart;class MyTextField e…

Moonlight for ChromeOS 常见问题解决方案

Moonlight for ChromeOS 常见问题解决方案 项目基础介绍 Moonlight for ChromeOS 是一个开源的 NVIDIA GameStream 客户端&#xff0c;允许用户将他们的游戏从高性能的桌面电脑流式传输到运行 ChromeOS 的设备上。该项目还支持 Android 和 iOS/tvOS 平台。Moonlight for Chrome…

SQL语句:读操作、写操作、视图

文章目录读操作分类基础查询语句示例高级查询--分组查询、子查询、表连接、联合查询分组查询&#xff1a;子查询&#xff08;嵌套查询&#xff09;表连接联合查询写操作视图SQL&#xff1a;结构化查询语言读操作 重点是where查询&#xff0c;即高级查询部分 分类 DML &#…

Python 机器学习实战:基于 Scikit-learn

本文围绕《Python 机器学习实战&#xff1a;基于 Scikit-learn 的项目开发》展开&#xff0c;先介绍 Scikit-learn 库的基础特性与优势&#xff0c;再阐述机器学习项目开发的完整流程&#xff0c;包括数据收集与预处理、模型选择与训练、评估与优化等。通过具体实战案例&#x…

java里List链式编程

java里对list的操作&#xff0c;我们一遍使用for遍历&#xff0c;输出或改变里面的内容。单经常在代码里面我们发现&#xff0c;也可以使用这样的代码结构daPaymentActionVo.setApnolist(paymentActionVo.getApnolist().stream().map(PaymentActionVo.Voucher::getApno).collec…