【STM32】05.TIM定时器

一、PWM 概述

PWM(Pulse Width Modulation),中文叫脉冲宽度调制,是一种用数字信号来模拟模拟信号的技术。这种信号通常用于控制电机的速度、灯光的亮度等。
信号示意如下:

三、PWM关键参数

  • 频率(frequency):PWM信号的重复速率,单位通常是赫兹(Hz)。
  • 周期(period):从一个脉冲开始到下一个相同脉冲开始的时间间隔。
  • 占空比(duty):在一个周期内脉冲高电平持续时间与整个周期时间的比例。

    1个周期时间 = 1 / 频率

三、TIM定时器简介

TIM(Timer)定时器是STM32微控制器中非常重要的外设模块,用于各种定时、计数、PWM生成、输入捕获等应用。

**四、**TIM 定时器类型

|-------|----------------------------------------|-----------------|
| 定时器类型 | 主要特性 | 应用场景 |
| 基本定时器 | 16位向上计数,只能定时 | 基础延时、DAC触发 |
| 通用定时器 | 16位向上/向下计数,4通道,支持输入捕获/输出比较 | 输出PWM、输入捕获、输出比较 |
| 高级定时器 | 16位向上/向下计数,拥有通用定时器一样功能,并扩展了互补输出,死区控制功能 | 输出PWM、电机控制、电源管理 |

在《STM32F103xx数据手册中文版.pdf》第 5 页,外设资源数量表中,可以看到,STM32F103中等容量系列控制器有3个通用定时器和1个高级控制定时器。

五、 STM32定时器输出PWM

利用STM32高级 / 通用定时器的输出比较功能,都可以输出PWM。下面以高级定时器的输出比较功能讲解:

1. 时钟源选择

定时器时钟源一般选择内部72 MHz 时钟 CK_INT

2. 时基单元

2. 1 时基单元作用

从图中可看出,计数器CNT根据CK_CNT频率向上 / 向下计数,即每来一个CK_CNT脉冲,TIMx_CNT(计数器寄存器)值就加1。 当TIMx_CNT值与TIMx_ARR(自动重载寄存器)的设定值相等时就自动生成更新事件或中断,并且TIMx_CNT自动清零,然后自动重新开始计数。如此重复以上过程。
总结:时基单元的作用是产生一个精确的、周期性的时间基准,这个基准可以用来:

  • 驱动计数器,从而实现定时功能。
  • 触发其他事件,如更新中断、DMA请求等。

2. 2 时基频率

CK_CNT频率 = 定时器时钟源频率 / (预分频器值 + 1)
为什么是 "预分频器值 + 1"?手册规定:

3. 输出比较

输出比较就是通过定时器的外部引脚对外输出控制信号,如常用的 PWM 信号。

3. 1 PWM输出引脚

查阅《STM32F103xx数据手册中文版.pdf》中的表5-中等容量STM32F103xx引脚定义,例如:

可以看到 PA8 是 TIM1的通道1引脚。

3. 2 输出PWM逻辑


上图展示 STM32 定时器 "PWM1 模式 + 向上计数" 的工作逻辑:

  • 计数器 CNT 从 0 递增至自动重装值 ARR 后重置
  • 当 CNT < 比较值 CCR1 时,主输出 OC1 为高电平、互补输出 OC1N 为低电平
  • 当 CNT≥CCR1 时,OC1 切换为低电平、OC1N 切换为高电平
  • ARR 决定 PWM 周期,CCR1 控制占空比。
    (扩展:互补输出(如 OC1N)常用于电机驱动的 H 桥电路,通过与主输出的反相电平避免桥臂直通,实现电机的调速或正反转控制。)

3. 3 PWM周期计算

PWM 周期 = 计数一次时间 * 一个周期计数次数
= 1 / CK_CNT频率 * (ARR + 1)
例如:定时器时钟源频率为72MHz,预分频器寄存器PSC数值为 71,自动重装再寄存器ARR为 999
PWM 周期 = 1 / (72MHz / (71 + 1) ) * (999 + 1) = 1 / 1000Hz
PWM 频率 = 1 / PWM 周期 = 1KHz
为什么计数次数是ARR+1?看下图理解:

可以看到,定时器是从 0 开始计数,直到 ARR 值,这一过程包含了 "0 到 ARR" 共 (ARR+1) 个计数点。

3. 4 占空比计算

"PWM1 模式 + 向上计数下,占空比计算:
占空比 = ( ARR+1)/ (CCR+1)​×100%
例如,若设置 CCR=500(PWM 模式 1):有效电平计数次数 = 500+1=501;
占空比 = 501 / 1000 ×100%≈50.1%(接近 50% 的占空比)。

六、PWM输出配置

1. 硬件设计

以网关设备的PA8,即TIM1通道1输出PWM,控制LED灯的亮度为例:

2. STM32CubeMX配置



3. STM32CubeMX生成的代码分析


4. 编写用户代码

需要运行以下函数:

objectivec 复制代码
#include "tim.h" // 包含STM32CubeMX生成的TIM头文件 

HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // 启动定时器1的PWM输出 

__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, 300); // 设置定时器1,CCR1为300,这时PWM占空比30%

示例:

objectivec 复制代码
#include "app_main.h"
#include "main.h"
#include "tim.h" // 包含STM32CubeMX生成的TIM头文件
...省略显示中间代码

// 替代main函数中的while循环
void app_main(void)
{
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);         // 启动定时器1的PWM输出
    __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, 300); // 设置定时器1,CCR1为300,这时PWM占空比30%

    while (1)
    {
    }
}
相关推荐
不会代码的小猴1 小时前
6. Qt网络编程
开发语言·c++·笔记·qt·算法
caimouse1 小时前
ReactOS 图形系统分析(50):画笔子系统 — pen.c
c语言·开发语言·stm32
硅农深芯2 小时前
PDN仿真显示高频阻抗大意味着什么?
单片机·嵌入式硬件·pdn·阻抗·pi仿真
lingzhilab2 小时前
零知派——STM32F103驱动ST7789与INA219太阳能充电功率实时监测系统
stm32·单片机·嵌入式硬件
tq10862 小时前
从阿罗不可能定理到所有制:动态协调与资源再配置的理论逻辑
笔记
wuyk55512 小时前
98.C语言易混难点:字符数组与字符串指针的底层差异
c语言·开发语言·c++·stm32·嵌入式硬件·算法
峥无12 小时前
从0到1手撕红黑树:封装实现 my_map 与 my_set(SGI-STL 源码级深度解析)
开发语言·c++·笔记·算法·stl
不会代码的小猴13 小时前
3. 控件学习1
开发语言·c++·笔记·qt·算法
恒锐丰-罗生13 小时前
国产 H 桥驱动 SS6289|18V/4A 有刷电机驱动芯片性与应用分析 内置采样 + 多保护,门锁 / 机器人优选器件
驱动开发·嵌入式硬件·硬件工程