一、定时器基础:STM32定时器家族概览
各位同学,咱们今天聊聊STM32的定时器。说实话,我刚开始接触STM32时,看到参考手册里那一堆定时器,头都大了。什么基本定时器、通用定时器、高级定时器,光名字就够绕的。但用久了你会发现,这东西其实挺有规律的。
定时器在嵌入式系统里,说白了就是个会数数的硬件。你给它一个时钟,它就开始计数,计到某个值就触发个中断,或者翻转个IO口。就这么简单。但STM32把这事儿玩出了花,搞出了三个等级的定时器。
1.1 定时器家族:三个等级,各司其职
STM32的定时器分三类,我习惯把它们比作工具:
- 基本定时器(TIM6、TIM7):就是个计时器,只能做基础的时间基准。我在项目里常用它来做系统心跳,比如每隔1ms触发一次中断,更新系统时钟。
- 通用定时器(TIM2~TIM5、TIM9~TIM14):功能就丰富多了。除了计时,还能做输入捕获、输出比较、PWM生成。说白了,大部分项目用通用定时器就够了。
- 高级定时器(TIM1、TIM8):这是大哥级别的。除了通用定时器的所有功能,还支持互补输出、死区插入、刹车功能。做电机控制、电源逆变这些场合,非它不可。
我记得有一次做无刷电机驱动,一开始用通用定时器凑合,结果发现死区时间控制不了,电机在换相时直接短路了。嗯,从那以后,电机控制我必用高级定时器。
核心要点:选定时器时,先看需求。只是计时?基本定时器够了。需要PWM?通用定时器。电机控制?直接上高级定时器,别犹豫。
1.2 定时器时钟源与时钟树
定时器要工作,得有时钟。STM32的时钟树,说实话,第一次看确实有点懵。但你可以这么理解:
定时器的时钟源主要有三个:
- 内部时钟(CK_INT):来自APB总线,最常用。我一般直接用这个,省事。
- 外部时钟模式1(TIx):从定时器的输入引脚进来。比如你想统计外部脉冲个数,就用这个模式。
- 外部时钟模式2(ETR):从专门的ETR引脚输入。我曾在编码器测速项目里用过,精度不错。
这里有个坑,我提醒一下:APB1和APB2的时钟频率可能不一样。比如STM32F103,APB1最高36MHz,APB2最高72MHz。如果你把定时器挂在APB1上,却想让它跑72MHz,那是不可能的。我曾经因为这个排查了半天,最后发现是时钟配置错了。
小技巧:配置时钟时,先确认定时器挂在哪个总线上,再看APB的预分频系数。如果APB预分频系数不是1,定时器时钟会是APB时钟的2倍。这个细节,很多人会忽略。
1.3 核心寄存器:七个关键角色
定时器的寄存器不少,但常用的就七个。我一个个说:
| 寄存器 | 全称 | 作用 |
|---|---|---|
| TIMx_CR1 | 控制寄存器1 | 控制定时器的使能、计数方向、自动重装载等 |
| TIMx_SMCR | 从模式控制寄存器 | 配置定时器的同步模式、触发源等 |
| TIMx_DIER | DMA/中断使能寄存器 | 开启各种中断和DMA请求 |
| TIMx_SR | 状态寄存器 | 查看各种事件是否发生 |
| TIMx_CNT | 计数器寄存器 | 当前计数值,实时读取 |
| TIMx_PSC | 预分频器寄存器 | 对时钟进行分频,范围1~65535 |
| TIMx_ARR | 自动重装载寄存器 | 计数的上限值 |
我个人的习惯是,配置定时器时按这个顺序来:
- 先配PSC和ARR,确定定时周期
- 再配CR1,设置计数模式
- 然后配DIER,开启需要的中断
- 最后置位CR1的CEN位,启动定时器
举个例子,配置一个1ms的定时器中断:
// 假设定时器时钟为72MHz
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 72 - 1; // 预分频,72MHz/72 = 1MHz
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 1000 - 1; // 自动重装载值,1MHz/1000 = 1kHz
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim2);
HAL_TIM_Base_Start_IT(&htim2);
这里要注意,PSC和ARR都是16位的,最大值65535。如果你需要更长的定时,可以级联两个定时器,或者用32位的定时器(比如TIM2、TIM5在有些系列里是32位的)。
避坑指南:我曾经在配置PSC时,直接写了72,结果定时器没反应。后来才发现,PSC的值是实际分频系数减1。也就是说,你想分频72倍,得写71。这个坑,新手几乎都会踩一次。
1.4 知识体系总览
下面这张图,是我自己画的定时器知识框架。你看一眼,心里就有数了:
这张图把定时器的分类、时钟源、核心寄存器和应用场景串起来了。你把它存下来,以后配置定时器时对着看,思路会清晰很多。
好了,这一章就到这里。定时器的基础框架已经搭好了,后面我们会一步步深入每个细节。记住,定时器这东西,多动手配置几次,自然就熟了。