STM32F4通用定时器TIM9-TIM14讲解及PWM呼吸灯实例解读
- 前言
- 小贴士
- 通用定时器原理
- 定时器的内部时钟源
- 通用定时器TIM9-TIM14的对比
- 共同点
- 区别
- TIM9-TIM14功能说明
- 时基单元
- 计数模式
- 时钟选择
- 定时器框图理解和分析
- TIM10/TIM11/TIM13/TIM14
- 输入捕获
- 输出比较
- TIM9和TIM12
- 独立通道
- 输入滤波器
- 边沿检测器
- 输入捕获选择器
- 预分频器
- 捕获比较寄存器
- 同步触发
- 触发选择TS[2:0]
- 主从模式联动
- 关于TRC的小提示
- PWM呼吸灯实例及解读
- 配置界面与寄存器
- PWM模式代码分析
- 初始化代码分析
- 初始化代码涉及的寄存器
- main函数中我们添加的代码
- 在初始化阶段调用的函数
- while(1)里添加的代码
- 寄存器分析
- TIMx_DIER
- TIMx_SR
- TIMx_EGR
- TIMx_CNT
- TIMx_PSC
- TIMx_ARR
- TIMx_CCR1
- 参考文献
前言
STM32F4的定时器分为高级定时器,通用定时器和基本定时器。上一篇文章已经讲了基本定时器。本文遵从由简入繁的原则,先讲解通用定时器的原理,并通过PWM实例帮助大家加深对通用定时器的理解,最后介绍通用定时器的寄存器,旨在帮助大家逐步掌握通用定时器的全部功能。本文一万余字,我倾注了些心血,如果对您有帮助,还请点赞、收藏、转发、评论!谢谢!
通用定时器分为:
- TIM2-TIM5
- TIM9和TIM12
- TIM10/TIM11/TIM13/TIM14
虽然都是通用定时器,也有细微的差别。本文讲解TIM10/TIM11/TIM13/TIM14和TIM9和TIM12两个部分。
小贴士
通用定时器的寄存器,有些名称中含有CC
,指的是“捕获/比较”,即Capture/Compare
,与独立通道的设置相关,可以将通道设置成输入型的,也可以设置成输出型的。输入则对应着捕获,输出则对应着比较。
通用定时器原理
定时器的内部时钟源
我们打开《STM32F4英文参考手册》看到时钟章节有时钟树,这里截取我们关心的定时器时钟。看得出来,芯片设计者对定时器和其他的外设是区别看待的。
很明显,对于APB1和APB2,都是一样的。由于STM32F4主频最高是168MHz,我们就假定SYSCLK = 168MHz。
就拿APB1举例,如果APB1的分频系数是1,也就是说,外设的工作频率是168MHZ,那么定时器的工作频率也是168MHZ;
但如果APB1的分频系数不是1,比如说是2,那么外设的工作频率是84MHz,这个时候,定时器的工作频率是84MHz的2倍,也就是168MHZ。
如果APB1的分频系数是4,那么外设的工作频率是42MHz,这个时候,定时器的工作频率是42MHz的2倍,也就是84MHZ。
所以相信大家看明白关系了。
通用定时器TIM9-TIM14的对比
共同点
对于TIM9-TIM14,它们的共同点是:
- 都是16位的自动重装载递增计数器(只能递增)
- 16位可编程预分频器
- 都拥有独立通道用于输出比较、输入捕获、PWM生成、单脉冲模式输出
- 可以产生中断的方法:更新、输入捕获、输出比较
区别
TIM9
和TIM12
比TIM10/TIM11/TIM13/TIM14
多的功能:
- 使用外部信号控制定时器且可实现多个定时器互连的同步
TIM9
和TIM12
拥有独立通道的数量比较多,分别有2个通道,而TIM10/TIM11/TIM13/TIM14
只有1个通道。- 相比而言,
TIM9
和TIM12
生成中断的条件多了一个:触发事件(计数器启动、停止、初始化或者由内部触发器计数)
TIM9-TIM14功能说明
时基单元
请参见基本定时器一文。
计数模式
请参见基本定时器一文。
时钟选择
TIM10/TIM11/TIM13/TIM14
和基本定时器一样,只有内部时钟(CK_INT)作为时钟源。
TIM9
和TIM12
除了可以使用内部时钟(CK_INT),还可以:
- 使用外部时钟模式(通过外部引脚输入时钟)
- 使用内部触发输入(ITRx)连接其他定时器的触发输出
对于TIM10/TIM11/TIM13/TIM14
,在基本定时器一文中已经有介绍时钟,所以这里只介绍TIM9
和TIM12
。
对于SMS
,有以下几种可选项,分别代表不同功能。
- 000——禁止从模式,定时器的时钟由内部时钟提供。(本定时器独立计数,不听命于其他)
- 100——复位模式,出现所选触发输入(TRGI)的上升沿时,重新初始化定时器并产生更新事件
- 101——门控模式,触发输入(TRGI)为高电平的时候才使能计数器时钟,TRGI为低电平就立即停止计数,但不会复位计数器。(什么时候计数,什么时候暂停计数,完全取决于别人的脸色)
- 110——触发模式,触发信号(TRGI)出现上升沿则启动计数,但不复位。(别人一声令下,本定时器启动计数,但什么时候停止,不听别人的。)
- 111——外部时钟模式1,在所选触发输入的上升沿驱动计数器。(来一个上升沿,我计一个数,再来一个上升沿,我又计一个数,如此往复……)
SMS
位其实对应到下图中的控制器:
定时器框图理解和分析
通过比较下面两张图片,可以直观感受到两种通用定时器的区别。
当然这两张图片是定时器的精髓,把这两张图看明白了,我们就掌握定时器了。“老太太吃柿子——捡软的捏”,咱们先看第二幅图,一眼望去,除了下面多了一个通道,上面的部分和基本定时器完全一样。而这条通道左边是外部引脚TIMx_CH1,右边也是TIMx_CH1。纳尼?什么意思?其实是这样的,它只是把一个引脚的功能“展开”了,一个定时器外部引脚,既可以输入,也可以输出。但不可能同时输入和输出,除非不同的引脚复用到这一个定时器上,然后让定时器分时复用,这种情况非常罕见,所以我们就当它是一个引脚就行。
TIM10/TIM11/TIM13/TIM14
输入捕获
“输入捕获”是对外部引脚输入的信号而言的;“输出比较”是对输出的信号而言的!分别对应着图上独立通道的左右两边。
如果这个引脚作为“输入捕获”功能,那么我们就不看右边的那半条通道。左边输入的时钟,经过滤波器和边沿检测器,给到预分频器,最后给了捕获/比较寄存器,通过计数值和这个寄存器的值相比,然后得出输入的时钟信息,比如高电平持续了多久?
输出比较
如果这个引脚作为“输出比较”功能,那么我们就不看左边的那半条通道,只看右边捕获/比较寄存器往右的这半条通道即可。相比之下,如果是“输入捕获”,则捕获/比较寄存器的值是随着输入信号写进去的,不是我们用户通过代码写值进去的;但如果是“输出比较”,则捕获/比较寄存器的值是我们用户通过写寄存器写值进去的。并且这个值可以随时被我们改变,这就是PWM的生成逻辑。
到此,第二张图TIM10/TIM11/TIM13/TIM14
定时器框图已经分析完毕。这里先给大家简单介绍一下,下面讲TIM9和TIM12的时候,涉及寄存器的内容,在这里也可以对应。
TIM9和TIM12
现在,我们看第一张图片TIM9
和TIM12
定时器框图。是不是比第二张图复杂了一些?不过对比之后发现,也没太复杂,请听我一一道来。
从独立通道的数量来看,TIM9
和TIM12
拥有2条,从外部引脚TIMx_CH1或者TIMx_CH2进来,就是TI1和TI2。从左到右,这两条独立通道基本上完全一样。但也有唯一的区别:对于TI1,经过输入滤波和边沿检测之后,可以成为TI1F_ED
,连接到上面的选择器,与TRC
共同被选择。其他方面两个独立通道是完全一样的。
当SMS
位等于111时,就选择TI1F_ED
作为定时器的外部时钟,每个上升沿都触发一次计数。(关于SMS
前文已有讲解,此处不赘述)
独立通道
输入滤波器
我们沿着独立通道从左到右看,首先就是数字滤波器和边沿检测器。
1、首先,我们要考虑的是输入滤波器的采样频率,由寄存器TIMx_CCMR1->IC1F
决定。
边沿检测器
边沿检测器要根据寄存器的值选择上升沿还是下降沿作为触发的极性。
因为两个通道的寄存器位完全一样,所以介绍通道1为例即可。
首先,CC1P
这个位在输出模式下,表示有效电平是高电平还是低电平。如果=1,则有效电平是高电平,反之是低电平。
在输入模式下,CC1NP
和CC1P
两个BIT共同组成2BIT的寄存器位,就有四种不同的值,代表不同含义:
- 00——上升沿是输入捕获的触发极性。
- 01——下降沿是输入捕获的触发极性。
- 10——保留。
- 11——上升沿和下降沿都是输入捕获的触发极性。(在编码模式下不允许使用)
最后一个位是CC1E
。如果是输出模式,就决定了输出是否使能;如果是输入模式,就决定了捕获是否使能。
在PWM呼吸灯实例中,可以看到HAL库对这一位的处理是:初始化的时候就清零。而它的置位是由用户调用API启动的。
输入捕获选择器
经过滤波器和边沿检测器,就到了下图的选择器。
CC1S[1:0]
实际上对应着上面这个选择器。回到上面的定时器框图就理解了。
CC1S[1:0]
可以选择:
- 01——就是TI1FP1连接到IC1;
- 10——就是TI2FP2连接到IC1;
- 11——就是TRC连接到IC1。
以上是将CC1(捕获比较通道1)设置成输入型的。如果想要设置成输出型的,CC1S
等于00,比如PWM模式就需要将波形从引脚输出的外部。
举一反三,CC2S
的含义类似。
预分频器
再往右是预分频器,就是外部输入几个事件,才会完成一次捕获。如下图,分为几种情况:
- 00——不分频,每次检测到边沿输入,都完成一次捕获。
- 01——每检测到2次事件,完成一次捕获。
- 10——每检测到4次事件,完成一次捕获。
- 11——每检测到8次事件,完成一次捕获。
捕获比较寄存器
最后到了捕获/比较寄存器。CNT计数器分别与两个捕获/比较寄存器连接,可以进行捕获比较。
同步触发
触发选择TS[2:0]
还有一个问题需要我们留意:
ITR0-ITR3一共4路,都是其他主定时器输入的触发信号TRGI,还有TI1F_ED、TI1FP1、TI2FP2,这些都可以用来同步定时器。至于选择哪一个,由下面的寄存器决定:
那另一个问题来了,上面的ITR0-ITR3分别是什么意思呢?
主从模式联动
既然提到了寄存器TIMx_SMCR,那么就顺便讲一下MSM(Master/Slave Mode),它是用于控制定时器的主从模式联动。当多个定时器需要协同工作时(如级联触发、同步计数),MSM位可确保它们的操作严格同步。
- 功能:使能主从模式联动,确保触发信号从主定时器传递到从定时器时,两个定时器的操作严格同步。
- 取值:
0
:禁用主从模式联动。1
:启用主从模式联动(推荐配置)。
当MSM位被置1时:
- 主定时器接收到触发信号后,会先将触发信号传递给从定时器。
- 从定时器根据自身配置(如SMS位)响应触发信号(如复位计数器、启动计数)。
- 主定时器在确保从定时器完成响应后,再执行自身的操作(如更新TRGO输出)。
这一机制避免了主从定时器之间的时序竞争,确保同步精度。
关于TRC的小提示
最后请留意一下,上面的TRC可以被选择在独立通道上使用。
PWM呼吸灯实例及解读
配置界面与寄存器
这里的配置和下面的寄存器相关,所以将其补充在下面进行解读。
PWM模式的选择。
快速模式
PWM模式代码分析
初始化代码分析
上图漏说了一句:
/* Select the Output Compare Mode */tmpccmrx |= OC_Config->OCMode;
这是在配置OC1M
位,将配置值PWM1写入“输出比较1模式”位。
初始化代码涉及的寄存器
补充对应的寄存器,供大家深入理解。
CC1E这一位,在代码中先是清零,关闭输出。
main函数中我们添加的代码
在初始化阶段调用的函数
HAL_TIM_PWM_Start(&htim14, TIM_CHANNEL_1);
之后我们分析一下这个函数的内部逻辑。
while(1)里添加的代码
for(uint16_t i = 0; i < 500; i ++){__HAL_TIM_SET_COMPARE(&htim14, TIM_CHANNEL_1, i);HAL_Delay(9);}for(uint16_t i = 500; i > 0; i --){__HAL_TIM_SET_COMPARE(&htim14, TIM_CHANNEL_1, i);HAL_Delay(9);}
其中的宏定义:
#define __HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__) \(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1 = (__COMPARE__)) :\((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2 = (__COMPARE__)) :\((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3 = (__COMPARE__)) :\((__HANDLE__)->Instance->CCR4 = (__COMPARE__)))
本例中,使用的是channel1,此宏定义是设置CCR1寄存器的值。实现PWM占空比变化。
到此,PWM呼吸灯的实例及分析结束。
寄存器分析
上面已经讲了一些寄存器,这里就没有被提及的寄存器进行补充说明。
TIMx_DIER
所谓的使能位,就是一个开关。打开开关之后,下面的标志位一旦置位了,就会触发相应的中断;关闭了开关之后,即便下面的标志位置位了,也不会触发中断。
TIMx_SR
所谓“重捕获”,是说上次的捕获标志位还没有清零,下一次的捕获事件就又触发了。为了防止第2次的捕获事件丢失,所以这个寄存器就应运而生了。
TIMx_EGR
TIMx_CNT
由于TIM9-TIM14都只有递增的模式,所以这个寄存器的值只能递增计数。
TIMx_PSC
回顾上面的定时器框图,你可能还有印象,这个寄存器就是下面框图的预分频器。而预分频的时钟来源,就是CK_PSC
。
TIMx_ARR
重装载寄存器就是下图中红色框的这个。如果说,计数器是“吃包子的”,那么重装载寄存器就是“喂包子的”。是不是很形象?哈哈哈……
TIMx_CCR1
TIMx_CCR1
寄存器在输入和输出模式下的功能不同,在输出模式下,与OC1PE
相关。如果OC1PE=1
,写进TIMx_CCR1
寄存器的值会在产生更新事件之后生效;如果OC1PE=0
,则写进TIMx_CCR1
寄存器的值会立即生效。在输入模式下,这个寄存器只允许读,不允许写,它的值是最后一次输入捕获事件的计数值。
这里补充OC1PE
(输出比较预装载使能)位的定义。
同样有TIMx_CCR2
寄存器,由于仅仅是通道不同,所以不需要多讲了。
参考文献
《STM32中文参考手册》
《STM32英文参考手册》
本文到此结束,已经很详细地介绍了通用定时器TIM9-TIM14,相信您可以从中有所收获,期待您的点赞、转发、收藏、评论!