1. STM32定时器基础概念与分类
在嵌入式系统开发中,定时器是最基础也最重要的外设之一。STM32F103C8T6作为一款广泛使用的Cortex-M3内核微控制器,其定时器功能尤为强大。根据功能差异,STM32的定时器可分为三大类:
1.1 基本定时器(TIM6/TIM7)
- 位于APB1总线
- 核心功能:定时中断、触发DAC
- 结构简单,适合基础定时需求
- 16位计数器,最高72MHz时钟输入
注意:基本定时器没有输入捕获/输出比较功能,适合简单的定时任务如看门狗喂狗、周期性数据采集等。
1.2 通用定时器(TIM2-TIM5)
- 同样位于APB1总线
- 在基本定时器基础上增加:
- 输入捕获(测量脉冲宽度)
- 输出比较(生成PWM)
- 编码器接口(电机控制)
- 主从模式(多定时器联动)
1.3 高级定时器(TIM1/TIM8)
- 位于APB2总线,时钟频率更高
- 在通用定时器基础上增加:
- 死区控制(电机驱动关键功能)
- 互补输出(三相电机控制)
- 刹车功能(紧急停止)
- 重复计数器(高精度定时)
2. 定时器核心工作原理详解
2.1 时基单元三要素
每个定时器的核心都由三个寄存器构成:
-
预分频器(PSC):对输入时钟进行分频
- 公式:f_CNT = f_CK_PSC / (PSC + 1)
- 例如72MHz时钟,PSC=71 → 1MHz计数频率
-
计数器(CNT):记录当前计数值
- 16位范围:0-65535
- 支持向上/向下/中心对齐三种计数模式
-
自动重装载寄存器(ARR):设定计数上限
- 计数到ARR值时触发更新事件
- 可配置预装载(修改ARR不影响当前周期)
2.2 定时器中断配置流程
以TIM2定时500ms为例:
c复制// 初始化结构体
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 7199; // 72MHz/(7199+1)=10kHz
htim2.Init.Period = 4999; // 5000个周期=500ms
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_Base_Init(&htim2); // 初始化时基
HAL_TIM_Base_Start_IT(&htim2); // 启动中断
避坑指南:HAL库中Period参数实际配置的是ARR-1,这与直接寄存器操作不同,需要特别注意。
3. PWM生成实战解析
3.1 PWM关键参数
- 频率:f_PWM = f_CK_PSC / [(ARR+1)*(PSC+1)]
- 占空比:Duty = CCR / (ARR+1)
以生成1kHz PWM为例:
c复制// 72MHz时钟,PSC=71 → 计数器频率1MHz
// ARR=999 → 1000个计数周期=1ms(1kHz)
htim3.Init.Prescaler = 71;
htim3.Init.Period = 999;
// 配置通道1为PWM模式1
TIM_OC_InitTypeDef sConfigOC;
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500; // 初始占空比50%
HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
3.2 呼吸灯实现技巧
c复制// 渐变占空比实现呼吸效果
for(int i=0; i<1000; i++) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, i);
HAL_Delay(1); // 1ms步进
}
经验分享:使用DMA自动更新CCR可实现更平滑的渐变效果,避免CPU频繁干预。
4. 输入捕获模式精要
4.1 测量脉冲宽度原理
- 上升沿捕获CNT值→T1
- 下降沿捕获CNT值→T2
- 脉冲宽度 = (T2-T1)*时钟周期
4.2 配置要点
c复制// 配置输入捕获通道
TIM_IC_InitTypeDef sConfigIC;
sConfigIC.ICPolarity = TIM_ICPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1);
// 启动捕获
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
5. 高级应用技巧
5.1 定时器级联
通过主从模式实现长周期定时:
- 主定时器配置为触发输出(TRGO)
- 从定时器配置为触发输入(TS=ITRx)
- 从定时器只在主定时器溢出时计数
5.2 编码器接口配置
c复制// 配置编码器模式
TIM_Encoder_InitTypeDef sConfig;
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
HAL_TIM_Encoder_Init(&htim3, &sConfig);
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
6. 常见问题排查
6.1 定时不准的可能原因
- 时钟源配置错误(检查RCC配置)
- 未考虑APB分频器的影响(当APB分频≠1时,定时器时钟会倍频)
- 中断响应延迟(检查中断优先级)
6.2 PWM无输出检查清单
- GPIO是否配置为复用功能
- 定时器时钟是否使能
- PWM通道是否启动
- 输出引脚是否被其他外设占用
7. 性能优化建议
- 使用DMA:对于频繁更新的PWM应用(如LED矩阵),使用DMA自动传输CCR值
- 利用互补输出:电机控制中使用TIM1/TIM8的互补输出和死区控制
- 定时器同步:多定时器应用时,使用主从模式保持同步
- 低功耗优化:在低功耗模式下,选择LSI作为时钟源
通过合理运用STM32定时器的这些高级特性,可以构建出从简单的LED闪烁到复杂的电机控制系统等各种应用。实际开发中,建议结合《STM32参考手册》的定时器章节和CubeMX的图形化配置工具,能更高效地完成定时器相关功能的开发。