TIM
目录
- TIM定时器
- 0. 定时器的分类和结构
- 1. 定时器基础参数与时基配置 (Base & Timebase)
- 2. 定时中断 (Timer Interrupt)
- 3. PWM 输出 (Pulse Width Modulation)
- 4. 输出比较 (Output Compare - OC)
- 5. 输入捕获 (Input Capture - IC)
- 6. 组合通道 (Combined Channels) 与 PWM 输入模式
- 7. 编码器模式 (Encoder Mode)
- 8. 触发源 (Trigger Source) 与主从模式
- 9. 使用了 CubeMX 后你不用关心的细节
- 10. 常用 API 速查表
TIM定时器
0. 定时器的分类和结构

1. 定时器基础参数与时基配置 (Base & Timebase)
这是所有定时器功能的地基,无论使用 PWM 还是编码器,首先都要配置时基。
基本概念
-
CK_INT: 内部时钟源频率(通常由 APB1 或 APB2 总线提供,需查阅 Clock Tree)。
-
PSC (Prescaler): 预分频系数(16位,0~65535)。
-
ARR (AutoReload Register): 自动重装载值(周期值)。
-
CNT (Counter): 当前计数值。
CubeMX 配置细节
-
Pinout & Configuration: 选择 TIMx。
-
Clock Source: 选择
Internal Clock(通常情况)。 -
Parameter Settings:
-
Prescaler (PSC): 输入 $N-1$。例如分频 72,输入
71。 -
Counter Mode:
Up(向上计数) 最常用。 -
Counter Period (ARR): 输入 $M-1$。决定了溢出/更新的时间点。
-
Internal Clock Division (CKD): 数字滤波器使用的采样时钟分频,通常选
No Division。 -
Auto-reload preload:
Enable(建议开启,使修改 ARR 在下个更新事件生效,防止波形错乱)。
-
核心公式:
$$\text{溢出频率} = \frac{\text{CK_INT}}{(PSC+1) \times (ARR+1)}$$
$$\text{溢出时间} = \frac{(PSC+1) \times (ARR+1)}{\text{CK_INT}}$$
2. 定时中断 (Timer Interrupt)
最基础的功能,用于周期性执行任务。

CubeMX 配置细节
-
配置时基: 如上所述,计算好 PSC 和 ARR 以获得目标中断频率(例如 1ms 或 1s)。
-
NVIC Settings:
-
Enabled: 必须勾选
TIMx global interrupt。 -
Preemption Priority: 根据系统实时性要求设置优先级。
-
代码实现
-
启动:
c // 在 main.c 的 user code begin 2 HAL_TIM_Base_Start_IT(&htim2); // 启动定时器并开启更新中断 -
回调函数:
c // 在 main.c 或任意源文件中重写 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) { // 执行周期性任务,例如 1ms 一次 // 注意:不要在此执行耗时操作(如 printf 延迟) } }
3. PWM 输出 (Pulse Width Modulation)
基于 4.输出比较 实现, 用于电机调速、LED 呼吸灯、蜂鸣器驱动。
CubeMX 配置细节
-
Mode: 在 Pinout 中将 Channel x 选为
PWM Generation CHx。 -
Configuration -> Parameter Settings:
-
Counter Settings: 配置 PSC 和 ARR 决定 PWM 频率。
-
PWM Generation Channel x:
-
Mode:
-
PWM mode 1(常用): CNT < CCR 时有效。 -
PWM mode 2: CNT > CCR 时有效。
-
-
Pulse (CCR): 初始占空比数值。$\text{Duty} = \frac{CCR}{ARR+1}$。
-
Output compare preload:
Enable(重要,防止修改占空比时产生毛刺)。 -
CH Polarity:
High(有效电平为高) 或Low。
-
-
代码实现
-
启动:
c HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // 开启 PWM 输出 -
运行时修改占空比:
c // 修改 CCR 寄存器,范围 0 ~ ARR __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 500);
4. 输出比较 (Output Compare - OC)
输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
与 PWM 类似但更灵活,用于生成精确的脉冲、相位控制或在特定时间翻转电平(Toggle)。它不强制要求连续波形。
CubeMX 配置细节
-
Mode: 将 Channel x 选为
Output Compare CHx。 -
Configuration -> Parameter Settings:
-
Output Compare Channel x:
-
Mode:
-
Toggle on match: CNT == CCR 时翻转引脚电平(常用,生成固定频率方波,频率为溢出频率的一半)。 -
Set active on match: 匹配时置高。 -
PWM mode: 其实 OC 也可以配成 PWM,但功能少于专用 PWM 模式。
-
-
Pulse: 初始比较值。
-
-
-
NVIC Settings: 如果需要在匹配时触发中断处理(例如相位控制),需要开启 NVIC。
代码实现
-
启动:
```c // 方式1: 仅输出电平,不进中断 HAL_TIM_OC_Start(&htim3, TIM_CHANNEL_1);
// 方式2: 开启输出并开启匹配中断 HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_1); ```
-
中断回调 (如果开启了 IT):
c void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { // 匹配事件发生,可以在此动态修改下一次的 CCR 值以改变相位 uint32_t current_ccr = __HAL_TIM_GET_COMPARE(htim, TIM_CHANNEL_1); __HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, current_ccr + offset); } }
5. 输入捕获 (Input Capture - IC)
输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数
用于测量外部信号的脉宽、周期、频率。
CubeMX 配置细节
-
Mode: Channel x 选为
Input Capture direct mode。 -
Configuration -> Parameter Settings:
-
Counter Settings: 配置 PSC 使得定时器不那么快溢出,但精度又要足够。
-
Input Capture Channel x:
-
Polarity:
Rising Edge(上升沿) 或Falling Edge(下降沿)。 -
Selection:
Direct(TI1映射到IC1)。 -
Prescaler: 这里的预分频是对输入信号的分频(例如每8个沿捕获一次),测高频时有用,通常选
No prescaler。 -
Input Filter:
0~15,数字滤波,滤除输入信号毛刺。
-
-
-
NVIC Settings: 必须开启
TIMx global interrupt。
代码实现
-
启动:
c HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); -
测量逻辑 (回调函数):
```c uint32_t val1 = 0, val2 = 0; uint8_t capture_idx = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { if (capture_idx == 0) { val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); capture_idx = 1; } else { val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // 处理溢出逻辑(如果 val2 < val1,说明中间发生过 ARR 溢出) // 计算周期 = val2 - val1 (需考虑溢出补偿) capture_idx = 0; } } } ```
6. 组合通道 (Combined Channels) 与 PWM 输入模式
CubeMX 中的 Combined Channels 选项通常用于特殊的硬件绑定功能,最典型的是 PWM Input Mode(同时测量频率和占空比)或 Encoder Mode、Hall Sensor Mode。
以 PWM Input Mode 为例(这是一个非常强大的功能,用一个定时器引脚同时捕获周期和脉宽):
CubeMX 配置细节
-
Mode:
-
Slave Mode:
Reset Mode(复位模式)。 -
Trigger Source:
TI1FP1(假设信号从 CH1 进)。 -
Combined Channels: 勾选
PWM Input on CH1(CubeMX 会自动把 CH2 变成 Indirect mode)。
-
-
Configuration:
-
Channel 1 (IC1): Polarity
Rising Edge(测周期),SelectionDirect。 -
Channel 2 (IC2): Polarity
Falling Edge(测占空比),SelectionIndirect。 -
原理: 上升沿触发 Reset(CNT清零)并由 IC1 捕获(此时是0,但下个周期就是周期值),下降沿由 IC2 捕获(此时是脉宽值)。
-
代码实现
// 启动 PWM 输入捕获(需要同时启动两个通道)
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);
// 在回调中读取
uint32_t IC1_Value = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1); // 周期 (Frequency)
uint32_t IC2_Value = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2); // 脉宽 (Duty)
if (IC1_Value != 0) {
float duty = (float)IC2_Value / IC1_Value * 100;
}
7. 编码器模式 (Encoder Mode)
用于读取旋转编码器(AB相)的信号,自动处理正反转。
CubeMX 配置细节
-
Mode:
- Combined Channels:
Encoder Mode。
- Combined Channels:
-
Configuration -> Parameter Settings:
-
Encoder Mode:
-
Encoder Mode TI1 and TI2: 4倍频模式 (精度最高,上下沿都计数)。 -
Encoder Mode TI1: 2倍频。
-
-
Counter Period (ARR): 通常设为最大
65535(16bit) 或4294967295(32bit),防止过快溢出。 -
Input Filter: 建议设为
10或更高,防止机械抖动误判。
-
-
NVIC: 通常不需要开启中断,除非你要计算多圈绝对位置(处理溢出)。
代码实现
-
启动:
c HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL); -
读取数据 (轮询):
```c // int16_t 强转是为了处理反转时的负数(补码) int16_t speed = (int16_t)__HAL_TIM_GET_COUNTER(&htim3);
// 读取后通常需要清零 CNT 以测量速度(单位时间内的脉冲数) __HAL_TIM_SET_COUNTER(&htim3, 0);
// 如果是测绝对位置,则不清零,需处理溢出逻辑 ```
8. 触发源 (Trigger Source) 与主从模式
这是 STM32 定时器的灵魂功能,允许硬件自动同步,无需 CPU 干预。
基本概念
-
ITR (Internal Trigger): 内部触发,定时器级联(如 TIM1 溢出触发 TIM2 启动)。
-
ETR (External Trigger): 外部引脚触发。
-
TIxFPx: 输入捕获引脚信号作为触发源。
常见应用场景:TIM1 主控 TIM2 (级联)
-
Master (TIM1) 配置:
- Trigger Output (TRGO):
Update Event(当 TIM1 发生更新/溢出时发送信号)。
- Trigger Output (TRGO):
-
Slave (TIM2) 配置:
-
Slave Mode:
External Clock Mode 1(外部时钟模式,即 TIM2 计数器的驱动不是内部晶振,而是 TIM1 的溢出脉冲)。 -
Trigger Source:
ITR0(查阅手册,ITR0 对应 TIM1)。
-
-
NVIC: 都不需要开中断,硬件全自动。
常见应用场景:外部引脚控制启停 (Gated Mode)
-
Slave (TIMx) 配置:
-
Slave Mode:
Gated Mode。 -
Trigger Source:
TI1FP1(CH1 引脚)。 -
效果: 当 CH1 为高电平时,定时器计数;低电平时,定时器暂停。
-
代码实现
大部分配置在 MX_TIMx_Init 中自动生成 (HAL_TIM_SlaveConfigSynchro)。
用户只需启动定时器:
HAL_TIM_Base_Start(&htim1); // 启动主定时器
HAL_TIM_Base_Start(&htim2); // 启动从定时器
9. 使用了 CubeMX 后你不用关心的细节
-
时钟使能 (__HAL_RCC_TIMx_CLK_ENABLE):
CubeMX 自动在 stm32fxxx_hal_msp.c 的 HAL_TIM_Base_MspInit 中生成。
-
GPIO 复用映射 (AF):
CubeMX 自动配置 GPIO 的 Alternate Function 寄存器(如将 PA6 复用为 TIM3_CH1)。
-
中断清除:
HAL 库的通用中断处理函数 HAL_TIM_IRQHandler 会自动读取并清除 SR 寄存器的标志位,然后才调用你的 Callback。不要在 Callback 里手动清除标志位,否则可能导致逻辑错误。
-
结构体初始化:
TIM_HandleTypeDef、TIM_OC_InitTypeDef 等繁琐的结构体赋值全部自动化。
10. 常用 API 速查表
| 功能 | API | 备注 |
|---|---|---|
| 启动/停止 (无中断) | HAL_TIM_Base_Start, HAL_TIM_Base_Stop |
基本计数 |
| 启动/停止 (带中断) | HAL_TIM_Base_Start_IT, HAL_TIM_Base_Stop_IT |
周期任务 |
| PWM 操作 | HAL_TIM_PWM_Start, __HAL_TIM_SET_COMPARE |
调速/调光 |
| 输入捕获 | HAL_TIM_IC_Start_IT, HAL_TIM_ReadCapturedValue |
测频/测宽 |
| 编码器 | HAL_TIM_Encoder_Start, __HAL_TIM_GET_COUNTER |
测速/位置 |
| 设置 CNT | __HAL_TIM_SET_COUNTER(&htimx, value) |
修正计数值 |
| 设置 ARR | __HAL_TIM_SET_AUTORELOAD(&htimx, value) |
动态改周期 |
| # 11. RCC时钟树 | ||
![]() |
# 经验
- Encoder不能和定时中断、输出比较(PWM)一起用,因为Encoder会:1.使用CCR寄存器(与PWM冲突)2. 归零counter 与定时中断溢出冲突
