STM32 的定时器(Timer)是 MCU 内部的一个重要外设,广泛用于精确计时、事件计数、PWM 生成、输入捕获等功能。我们可以把定时器比喻成一个精确的电子时钟,它可以计时、闹钟、秒表、定时提醒,甚至可以控制电灯亮灭、马达转速等外部设备。
1. STM32 定时器的分类
STM32 的定时器主要分为以下几类,它们在功能和用途上有所不同:
定时器类型 | 典型型号 | 主要功能 |
---|---|---|
高级定时器 | TIM1、TIM8 | 具有高级 PWM、死区控制,适合电机控制 |
通用定时器 | TIM2、TIM3、TIM4、TIM5、TIM9、TIM10、TIM11、TIM12、TIM13、TIM14 | 常规计时、PWM 输出、输入捕获、事件计数 |
基本定时器 | TIM6、TIM7 | 仅用于定时,不支持输入捕获/PWM,多用于DAC 触发 |
低功耗定时器 | LPTIM1、LPTIM2 | 低功耗应用(如休眠唤醒、RTC 相关) |
独立看门狗(IWDG) | IWDG | 防止程序卡死,自动复位 MCU |
窗口看门狗(WWDG) | WWDG | 检测代码异常、周期性喂狗,超时复位 |
其中,高级定时器(如 TIM1、TIM8)通常用于复杂的 PWM 控制,比如电机驱动,而通用定时器(如 TIM2-TIM5)则更常用于常规的 PWM、输入捕获、定时中断等功能。
2. 定时器的基本工作原理
2.1 定时器的核心组成
可以将 STM32 的定时器想象成一个电子秒表,它主要包含以下几个核心部件:
- 时钟源(Clock Source):提供定时器计数的时钟,通常是 APB1 或 APB2 时钟(经过分频)。
- 预分频器(Prescaler, PSC):用来调整计数的速度(相当于秒表的快慢调节)。
- 计数器(Counter, CNT):核心组件,记录时间的流逝(类似秒表的读数)。
- 自动重装载值(ARR,Auto Reload Register):设置定时器的最大计数值,计数到该值后可以自动清零并触发中断。
- 比较寄存器(CCR,Capture/Compare Register):用于 PWM 和输入捕获。
官方手册中的通用定时器结构图如下:
高级定时器的结构图如下:
基本定时器的结构如下:
2.2 计数模式
STM32 定时器有 3 种常见的计数模式:
- 向上计数模式(Up Mode):从 0 计数到
ARR
,然后清零重新计数。 - 向下计数模式(Down Mode):从
ARR
计数到 0,然后重新计数。 - 中心对齐模式(Center-aligned Mode):先向上计数到
ARR
,然后反向计数到 0(适用于 PWM)。
计数模式示意图:
Up Mode: 0 → 1 → 2 → … → ARR → 0 → 1 → ...
Down Mode: ARR → … → 2 → 1 → 0 → ARR → ...
Center Mode: 0 → 1 → … → ARR → … → 1 → 0 → ...
3. STM32 定时器的主要功能
3.1. 定时中断
定时器最常见的功能是定时触发中断。比如,我们可以让 STM32 每隔 1 秒 触发一次中断,在中断里执行一些任务(比如控制 LED 闪烁)。
示例:配置 TIM2 每秒触发一次中断
void Timer2_Init(void) {
__HAL_RCC_TIM2_CLK_ENABLE(); // 使能 TIM2 时钟
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 7200 - 1; // 预分频 7200(假设 APB1 时钟 72MHz)
htim2.Init.Period = 10000 - 1; // 计数 10000 次(总共 1 秒)
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_Base_Init(&htim2);
HAL_TIM_Base_Start_IT(&htim2); // 启用中断模式
}
3.2. PWM 输出
定时器可以用来生成 PWM(脉冲宽度调制)信号,常用于控制舵机、电机,或者调节 LED 亮度。
示例:TIM2 生成 50Hz PWM 信号
void PWM_Init(void) {
TIM_HandleTypeDef htim2;
TIM_OC_InitTypeDef sConfigOC;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 720-1; // 预分频 720
htim2.Init.Period = 2000-1; // PWM 频率 50Hz(=72MHz / 720 / 2000)
HAL_TIM_PWM_Init(&htim2);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 150; // 设定 PWM 占空比(可调)
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}
3.3. 输入捕获
输入捕获(Input Capture)用于测量外部信号的频率或脉宽,比如超声波测距、红外遥控解码等。
📌 示例:使用 TIM1 捕获外部信号
void Input_Capture_Init(void) {
TIM_HandleTypeDef htim1;
TIM_IC_InitTypeDef sConfigIC;
htim1.Instance = TIM1;
htim1.Init.Prescaler = 72-1; // 预分频 72(假设 72MHz 时钟)
htim1.Init.Period = 0xFFFF; // 16-bit 计数
HAL_TIM_IC_Init(&htim1);
sConfigIC.ICPolarity = TIM_ICPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);
}
3.4. 事件计数
定时器还能用来计数外部信号的脉冲,适用于 计步器、编码器 等应用。
4. 总结
STM32 定时器就像一个可编程的电子计时器,可以用来:
✅ 定时触发事件(定时中断)
✅ 产生 PWM 信号(控制 LED、舵机、电机)
✅ 测量脉冲信号(输入捕获,用于超声波测距等)
✅ 计数外部事件(编码器、电机测速)