前言
在STM32中,定时器起着至关重要的作用,它设计复杂但功能强大,针对不同的情境有严谨的设计。
一、TIM简介
定时器就是一个计数器,当这个计数器的输入是一个准确可靠的基准时钟的时候。那它在对这个基准时钟进行计数的过程实际上就是计时的过程。在STM32中,定时器的基准时钟一般都是主频72MHz,如果对72MHz计72个数,是1MHz也就是1us 的时间;如果计72000个数,是1KHz也就是1ms的时间。
这三个寄存器构成了定时器最核心的部分,这一块电路称为时基单元。时基单元里的计数器、预分频器、自动重装寄存器都是16位的,2的16次方是65536,也就是如果预分频器设置最大,自动重装寄存器也设置最大,那定时器的最大定时时间就是59.65s,接近一分钟。STM32的定时器还支持级联的模式,也就是一个定时器的输出,当作另一个定时器的输入。这样加一起,最大定时时间就是59.65s×65536×65536,这个时间大概是八千多年。
二、STM32的三种定时器
不同定时器连接的总线也不同,高级定时器连接的是性能更高的APB2总线,通用定时器和基本定时器连接的是APB1总线,在RCC开启时钟时要注意。
基本定时器功能最少,只有基本的定时中断功能和一个主模式触发DAC的功能,所以基本定时器还可以和DAC联合使用。
通用定时器拥有基本定时器的全部功能,也就是定时中断功能和主模式触发DAC的功能。并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能。
高级定时器最为复杂,拥有通用定时器的全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能。这些功能主要是为了三相无刷电机的驱动设计的。
2.1基本定时器
基本定时器框图:
图中预分频器、计数器、自动重装寄存器,它们构成了最基本的计数计时电路,统称时基单元。
2.1.1定时中断功能
1. 时钟源
基本定时器只能选择内部时钟CK_INT。内部时钟的来源是定时器时钟 TIMxCLK,这里的频率值一般都是系统的主频72MHz,所以通向时基单元的定时器时钟频率就是72MHz。
2. 预分频器
由图中可知定时器时钟经过 PSC 预分频器之后,为 CK_CNT,它可驱动计数器计数。即PSC预分频器可以对72MHz的定时器时钟频率进行预分频。预分频器是16位的,可以对定时器时钟 TIMxCLK 进行 1~65536 之间的任何一个数进行分频。具体计算方式为:CK_CNT=TIMxCLK/(PSC+1)。
- 若预分频器写0,实际就是1分配,就是不分频。输出频率=内部时钟的CK_INT输入频率=72MHz;
- 若预分频器写1,实际就是2分配,输出频率=内部时钟 CK_INT的输入频率/2=36MHz;
- 若预分频器写2,实际就是3分配,输出频率=内部时钟 CK_INT输入频率/3=12MHz;
3. 计数器
计数器可以对预分频后的计数时钟CK_CNT进行计数,计数时钟CK_CNT每来一个上升沿,计数器的值就加1。这个计数器也是16位的,它的值可以从0一直加到65535,如果已经加到65535再加的话,计数器就会回到0重新开始。所以计数器的值在计时过程中会不断自增运行,当自增运行到目标值时,产生中断,计时器就完成了定时任务。
因为这个目标值需要存储,所以还需要一个存储目标值的寄存器,那就是自动重装寄存器了。
4. 自动重装寄存器
自动重装寄存器也是16位的,它存的就是写入的目标值。在运行的过程中,计数值不断自增,自动重装寄存器中写入的值是固定的目标值,当计数值等于自动重装寄存器中的目标值时,也就是计时时间到了,就会产生一个中断信号,并且清零计数器,计数器自动开始下一次的计数计时。
5.更新中断和更新事件
图中向上的折线箭头表示在它的位置处会产生中断信号,而计数值等于自动重装寄存器目标值时产生的中断一般称它为更新中断,在这个更新中断之后就会通往NVIC,就需要再配置好NVIC的定时器通道,这样定时器的更新中断就能够得到CPU的响应了。
图中向下的折线箭头表示在它的位置处会产生一个事件,在图中更新中断下方处的事件一般称它为更新事件。更新事件不会触发中断,但可以触发内部其他电路的工作。
总结:系统主频率从基准时钟到预分频器分频再到计数器,计数器计数自增,同时不断地与自动重装寄存器的目标值进行比较,当值相等时,计时时间到,这时会产生一个更新中断和更新事件。CPU响应更新中断,就完成了定时中断任务了。
2.1.2主模式触发DAC功能
主模式触发DAC功能能让内部的硬件在不受程序的控制下实现自动运行。主从触发在某些情景下将会极大地减轻CPU的负担。
DAC 为数字/模拟转换模块,它的作用就是把输入的数字编码,转换成对应的模拟电压输出一段波形,需要每隔一段时间来触发一次DAC,让它输出下一个电压点。
如果用使用中断的思路来实现的话,就是先设置一个定时器产生中断,每隔一段时间在中断程序中调用代码手动触发一次DAC转换,然后DAC输出。但是这样主程序就会频繁处于被中断的状态,这会影响主程序的运行和其他中断的响应。
使用主模式可以把定时器的更新事件映射到触发输出TRGO(Ttigger Out) 的位置。因为TRGO是直接接到DAC的触发转换引脚上的,所以TRGO可以直接触发DAC。这样定时器的更新就不再需要通过中断来触发DAC转换了。整个过程不需要软件的参与,实现了硬件自动化,这就是主模式的作用。
2.2 计数模式
上文中基本定时器的计数器计数模式都是向上计数的模式。但是对于通用定时器而言,计数器的计数模式不止向上计数这一种。通用定时器有以下三种计数模式可以选择:
- 向上计数模式:计数器从0开始,向上自增,计到和自动重装寄存器的目标值相等时,计数器清零同时申请中断。然后开始下一轮,依次循环。
- 向下计数模式:计数器从自动重装寄存器的目标值开始,向下自减,减到0之后,回到目标值同时申请中断,然后开始下一轮,依次循环。
- 中心对齐模式:计数器从0开始,先向上自增,计到和自动重装寄存器的目标值相等时,申请中断,然后再向下自减,减到0之后,再申请中断。然后开始下一轮,依次循环。
基本定时器仅支持向上计数这一种模式,通用定时器和高级定时器支持向上计数、向下计数、中心对齐三种模式。当然最常用的还是向上计数模式。
2.2通用定时器
通用定时器框图:
2.2.1 时钟源
对于基本定时器而言,定时器只能选择内部时钟,也就是系统频率72MHz。而通用定时器的时钟源不仅可以选择内部的72MHz时钟,还可以选择外部时钟。
通用控制定时器有四个时钟源可选:
TIMx_ETR引脚处可接外部时钟,ETR(External)引脚的位置可以参考引脚定义表(之前博客连接中有https://blog.csdn.net/Echo_cy_/article/details/134038849?spm=1001.2014.3001.5501)
下图为引脚定义表局部截图。可以看到表格第一行有TIM2_CH1_ETR,意思是TIM2的CH1和ETR都是复用在了PA0引脚的位置。还有CH2、CH3、CH4和其他定时器的一些引脚也都可以在表中找到。
外部时钟模式2
选择引脚为TIM2的ETR引脚,也就是在PA0上接一个外部方波时钟。配置一下内部的极性选择、边沿检测和预分频电路,再配置一下输入滤波电路。这两块电路可以对外部时钟进行一定的整形。因为外部引脚的时钟难免会有一些毛刺,这些电路可以对输入的波形进行滤波。同时也可以选择一下极性和预分频器。
滤波后的信号兵分两路,上面一路ETRF进入触发控制器,紧跟着就可以选择作为时基单元的时钟了。如果想在ETR外部引脚提供时钟,或者相对ETR时钟进行计数,把这个定时器当作计数器来用的话就可以配置这一路的电路。在STM32中,这一路也叫做“外部时钟模式2”。
外部时钟模式1
滤波后的信号除了进上面一路ETR可以提供时钟外,下面还有一路可以提供时钟,就是TRGI(Trigger In)从它的名字可以知道,它主要是用作触发输入的,这个触发输入可以触发定时器的从模式。本章节主要讲触发输入作为外部时钟来使用的情况,暂且可以把TRGI当作外部时钟的输入来看。把TRGI当作外部时钟来使用的这一路电路叫做“外部时钟模式1”。外部时钟模式1的输入有以下四种信号。
1.ETR引脚信号
ETR引脚的信号,这里ETR引脚既可以通过上方ETRF这一路进来当作时钟(外部时钟模式2);又可以通过下方TRGI这一路进来当作时钟,这两种情况对于时钟输入而言是等价的,只是下方这一路输入会占用触发输入的通道而已。通过下方TRGI这一路进来当作时钟的电路为外部时钟模式1。
2.其他定时器信号
可以选择通过ITR的这一路,这一部分的时钟信号是来自其他定时器的。主模式的输出TRGO可以通向其他定时器。当通向其他定时器的时候,就接到了其他定时器的ITR引脚上了。ITR0~ITR3是分别来自其他4个定时器的TRGO输出。具体ITR和定时器的连接关系参考下表:
表中可以看到TIM2的ITR0是接在TIM1的TRGO上;TIM2的ITR1是接在TIM8的TRGO上;TIM2的ITR2是接在TIM3的TRGO上;TIM3的ITR0是接在TIM4的TRGO上……
通过ITR这一路可以实现定时器级联的功能。比如可以先初始化TIM3,然后使用主模式把它的更新事件映射到TRGO上,接着再初始化TIM2,这里选择ITR2,对应的就是TIM3的TRGO,后面再选择时钟为外部时钟模式1,这样TIM3的更新事件就可以驱动TIM2的时基单元,也就实现了定时器的级联。
3.CH1引脚的边沿信号
可以选择通过TI1F_ED的这一路,这里连接的是输入捕获单元的CH1引脚,也就是从CH1引脚获得时钟,后缀ED(Edge)边沿的意思,也就是通过这一路输入的时钟,上升沿和下降沿均有效。
4.CH1引脚和CH2引脚信号
时钟还能通过TI1FP1和TI2FP2获得,其中TI1FP1连接到CH1引脚的时钟,TI1FP2连接到CH2引脚的时钟。
总结:
外部时钟模式1的输入可以是ETR引脚、其他定时器、CH1引脚的边沿、CH1引脚和CH2引脚。一般情况下外部时钟通过ETR引脚就可以了。
时钟最常用的是内部72MHz的时钟,外部时钟首选ETR引脚外部时钟模式2输入。
2.2.2 控制器
高级控制定时器控制器部分包括触发控制器、从模式控制器以及编码器接口。
TRGO是定时器主模式输出,这部分电路可以把内部的一些事件映射到TRGO引脚上.如基本定时器中将更新事件映射到TRGO,用于触发DAC。而这里可以把定时器内部的一些事件映射到TRGO引脚这里,用于触发其他定时器、DAC或ADC。由此可见通用定时器触发输出的范围比基本定时器更广。
2.2.3 时基单元
通用定时器中间最核心的一部分还是时基单元,这部分结构和基本定时器是一样的,由预分频器、计数器、自动重装寄存器组成。每部分的工作流程和基本定时器也是一样的。
预分频器对时钟进行预分频;计数器自增计数;当计数值计到自动重装寄存器的目标值时,计数值清零的同时产生更新中断和更新事件。
2.2.4 输入捕获
输出比较电路总共有四个通道,分别对应CH1到CH4的引脚,可以用于输出PWM波形,驱动电机。
2.2.5 捕获/比较寄存器
捕获/比较寄存器是输入捕获和输出比较电路共用的,因为输入捕获和输出比较不能同时使用,所以这里的寄存器是共用的,引脚也是共用的。
2.2.6 比较通道
输入捕获电路有四个通道,对应的有CH1到CH4的引脚,可以用于测量输入方波的频率等。
2.3 高级定时器
高级定时器框图:
2.3.1 重复计数器
在申请中断的地方,增加了一个重复次数计数器。计数器可以实现每隔几个计数周期才发生一次更新事件和更新中断。
没有重复次数计数器的结构是每个计数周期完成后就都会发生更新。而有重复次数计数器可以每隔几个周期更新一次,就相当于对输出的更新信号又做了一次分频。
对于高级定时器,在最大定时时间59s多上还需要再乘65536,这样又可以提升很多的定时时间。
2.3.2 输出比较模块
DTG(Dead Time Generate)是死区生成电路,上三路输出控制的输出引脚由一个变为两个互补的输出,可以输出一对互补的PWM波。这些电路是为了驱动三相无刷电机。因为三相无刷电机的驱动电路一般需要3个桥臂,每个桥臂有2个大功率开关管控制,总共需要6个大功率开关管来控制。所以这里的输入PWM引脚的上三路就变为了互补的输出,各有两个输出引脚。而第四路还是一个输出引脚是因为三相电机只需要有三路就行。
为了防止互补输出的PWM驱动桥臂时,在开关切换的瞬间,由于器件的不理想,造成短暂的直通现象。为了解决这一问题就在输出控制前加上了死区生成电路。在开关切换的瞬间让桥臂的上下管全都关断,防止直通现象。
2.3.3 刹车输入
刹车输入是为了给电机驱动提供安全保障的。如果外部引脚BKIN (Break IN) 产生了刹车信号;或者内部时钟失效,产生了故障。那么控制电路就会自动切断电机的输出防止意外发生。
三、定时中断基本结构
定时中断基本结构图:
由此图着重来看定时中断和内外时钟源选择所涉及的结构,图中间部分最重要的还是时基单元,由PSC(Prescaler)预分频器、CNT(Counter)计数器、ARR(AutoReloadRegister)自动重装寄存器构成。
时基单元下面是运行控制,就是控制寄存器的一些位,如启动停止、向上或向下计数等。操作这些寄存器就可以控制时基单元运行。
时基单元左边是为时基单元提供时钟的部分,可有多种选择:
以上这些就是定时器的所有可选时钟源了。
最下方还有一个编码器模式,一般为编码器独用模式,普通时钟用不到这个模式。
时基单元右边是计时时间到时产生更新中断后的信号去向。中断信号会先在状态寄存器里置一个中断标志位,标志位会通过中断输出控制到NVIC申请中断。中断输出控制用来判断中断输出是否被允许,它就相当于一个中断输出的允许位,如果需要某个中断就允许这个中断执行。
四、时序图
4.1 预分频器时序图
- 时序图1行CK_PSC预分频器的输入时钟。
- 时序图2行CNT_EN计数器使能,高电平计数器正常运行,低电平计数器停止。
- 时序图3行CK_CNT计数器时钟,它既是预分频器的时钟输出,也是计数器的时钟输入。
对应时基单元图:
时序图中可以看到,开始时计数器未使能,计数时钟不运行。使能后的前半段预分频器系数为1,计数器的时钟等于预分频器前的时钟;后半段预分频器系数变为2,计数器的时钟也变为预分频器前时钟的一半。
在计数器时钟的驱动下,时序图4行的计数器寄存器也跟随时钟的上升沿不断自增。在中间位置FC之后,计数值变为0了,可推断出ARR自动重装寄存器的目标值就是FC。当计数值计到和自动重装寄存器的目标值相等,并且下一个时钟来临时,计数值才清零。在这个时间还产生一个更新事件。
时序图6行和7行时序描述的是预分频寄存器的一种缓冲机制,预分频寄存器实际上有两个,一个是预分频器控制寄存器,可以读写用,但它不直接决定分频系数;另一个缓冲寄存器(影子寄存器)就是时序图中预分频缓冲器。缓冲寄存器才是真正起作用的寄存器。
在一个计数周期内,计数器计数计到一半时改变了分频值,这个变化并不会立刻生效,而是会等到本次计数周期结束时产生了更新事件,预分频寄存器的值才会被传递到缓冲寄存器里面去,才会生效。对应时序图,即使在计数中途改变了预分频值,计数频率仍然会保持为原来的频率,直到本轮计数完成,在下轮计数时改变后的分频值才会起作用。
时序图8行,预分频器内部也是靠计数来分频,当预分频值为0时,计数器就一直为0,直接输出原频率;当预分频值为1时,计数器就0、1、0、1、0、1……这样计数。当1回到0时,输出一个脉冲,这样输出频率就是输入频率的2分频。从时序图还能看到,预分频器的值和实际的分频系数之间有一个数的偏移。所以有公式:计数器计数频率 CK_CNT = CK_PSC / (PSC + 1) 。
4.2 计数器时序图
- 时序图1行CK_INT是内部时钟72MHz。
- 时序图2行CNT_EN计数器使能,高电平计数器正常运行,低电平计数器停止。
- 时序图3行CK_CNT计数器时钟,因为分频系数为2,所以频率是内部时钟频率除2。
- 时序图4、5、6、7行,计数器在计数时钟的每个上升沿自增。当增到0036时,达目标值。下一个上升沿计数器寄存器清零、计数器溢出、产生一个更新事件脉冲、更新标志位UIF置1。
更新标志位UIF置1了,就会去申请中断,中断响应后,需要在中断程序中手动清零。
计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1) 如果想算计数器溢出时间,只需要将计数器溢出频率取个倒数就行了。
预分频器为了防止中途更改数值造成错误,设计了缓冲寄存器。计数器也有这样的设计,在定时器结构图中带一个黑色阴影的寄存器都是有影子寄存器的缓冲机制的,包括预分频器、自动重装寄存器和捕获比较寄存器。所以用来计数的ARR自动重装寄存器也是有缓冲寄存器的,并且缓冲寄存器是否需要使用是可以设置的,通过设置ARPE位,就可以选择是否使用预装功能。
4.3 计数器无预装时序图
计数器没有缓冲寄存器的情况:
时序图4行,计数器正在进行自增计数,突然改了自动加载寄存器也就是自动重装寄存器,由FF改为36,那计数值的目标值就由FF变成了36。所以时序图4行处计数器计到36之后就直接更新,开始下一轮计数。
4.4 计数器有预装时序图
计数器有缓冲寄存器的情况:
时序图8行,自动加载寄存器在计数途中突然把计数目标由F5改成了36。时序图9行自动加载影子寄存器才是真正起作用的,它保持F5,所以现在这个周期的计数目标还是计到F5再产生更新事件。产生更新事件的同时要更改的36才被传递到影子寄存器,在下一个技术周期更改的36才有效。
引入影子寄存器的目的实际上是为了同步,就是让值的变化和更新事件同步发生,防止在运行途中更改造成错误。从时序图也可以看出,如果不使用影子寄存器的话,F5改到36立刻生效。但此时计数值已经到了F1,已超过36,F1只能增加,但它的目标值却是36,比F1小。这种情况下F1就只能一直加到FFFF最大值后再回到0,从0开始再加到36才能产生更新,这就会造成一些问题。
总结
以上就是今天要讲的内容,本文介绍了STM32的TIM定时器部分,讲述了基本定时器、通用定时器、高级定时器,着重讲述了最为常用的通用定时器。还通过时序图分析了时基单元运行的细节。
原文地址:https://blog.csdn.net/Echo_cy_/article/details/134643472
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_44240.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!