向上计数模式
在递增计数模式下,计数器从0计数到自动重载值(TIMx_ARR寄存器的内容),然后从0重新开始计数,并产生一个计数器溢出事件。
如果使用重复计数器,则在递增计数器重复了重复计数器寄存器(TIMx_RCR)中所编程的次数后,会产生更新事件(UEV)。否则,每次计数器溢出时都会产生更新事件。
设置 TIMx_EGR 寄存器的 UG
位(通过软件或从机模式控制器)也会产生一个更新事件。
UEV 事件可以通过软件将 TIMx_CR1 寄存器的UDIS
位置位来禁用。这是为了避免在预载寄存器中写入新值时更新影子寄存器。那么在UDIS
位被写入0
之前,不会发生更新事件。然而,计数器会从0
重新开始,预分频器的计数器也是如此(但预分频率不变)。此外,如果 TIMx_CR1 寄存器中的URS
位(更新请求选择)被置位,则置位UG
位会产生一个更新事件UEV
,但不会置位UIF
标志(因此不会发送中断或DMA请求)。这是为了避免在清除捕获事件计数器时同时产生更新和捕获中断。
发生更新事件时,所有寄存器都会更新,更新标志( TIMx_SR 寄存器中的UIF
位)也会被置位(取决于URS
位):
- 重复计数器被重新载入 TIMx_RCR 寄存器的内容,
- 自动重装载影子寄存器用预加载值(TIMx_ARR)更新,
- 预分频器的缓冲器重新载入预载值(TIMx_PSC 寄存器的内容)。
下面的这两张图至关重要,涉及到 TIMx_ARR 寄存器动态改变后,计数器时序图如何变化。这里面,前面的文章(STM32F0x高级定时器简介)中多次提到的TIMx_CR1中的ARPE
位,将发挥重要作用。
图47,计数器时序图,当ARPE=0
时更新事件(TIMx_ARR未预加载)
先看图47,TIMx_ARR的值更新后,自动重载预装载寄存器的值立即更新(最后一行)。TIMx_ARR原来的值是0xff
,那么第四行的Counter寄存器应该计数到0xff
才产生溢出,但是在计数器计数到0x32
的时候,TIMx_ARR被更新到了0x36
,图中这个设置是立即生效的,因为接下来第五行的定时器的溢出事件并没有计数到原来的0xff
,而是直接在计数到0x36
这个新设置的值后就重新开始跑了。这要归功于最重要的一项设置,就是ARPE=0
,意思就是不要预加载,改动立即生效(其实前面的文章已经讲过,就是让ARR的预加载寄存器立即更新到影子寄存器)。
图48,计数器时序图,当ARPE=1
时更新事件(TIMx_ARR预加载)
再看图48,最重要的一项改动,就是ARPE=1
。原先TIMx_ARR的值为0xf5
,但在第四行定时器的计数器跑到0xf1
的时候,ARR被改到了0x36
,请看图,这个改动立即生效了吗?这时Counter的值(0xf1
)大于了ARR的预加载值(0x36
),但时序图中的第五行并没有在这个时刻发生定时器溢出事件,第四行的计数器也没有被复位,而是继续跑。同时自动重装载影子寄存器也没有被更新,还是0xf5
。而是要等到什么时候?等到计数器跑到原先值0xf5
后这一切才被更新!
所以,ARPE
是干啥的?之前网上搜了大量文章硬是没搜出个名堂,现在终于解惑了!它就是对ARR预加载,不让改动立即生效,而是等到下一个更新事件到来,再把这个值传输到影子寄存器。
向下计数模式
在递减计数模式下,计数器从自动重载值(TIMx_ARR寄存器的内容)递减计数至0
,然后从自动重载值重新开始计数,并产生一个计数器下溢事件。
如果使用重复计数器,则在递减计数重复了重复计数器寄存器(TIMx_RCR)中设置的次数后,会产生更新事件(UEV)。否则,在每次计数器下溢时产生更新事件。
设置TIMx_EGR寄存器的UG
位(通过软件或从机模式控制器)也会产生一个更新事件。
UEV更新事件可以被软件禁用,通过设置TIMx_CR1寄存器的UDIS
位。这是为了避免在预载寄存器中写入新值时更新影子寄存器。那么在UDIS
位被写入0之前,不会发生更新事件。然而,计数器从当前自动重载值重新启动,而预分频器的计数器从0重新启动(但预分频率不变)。
此外,如果TIMx_CR1寄存器中的URS
位(更新请求选择)被置位,则置位UG
位会产生一个更新事件UEV,但不会置位UIF
标志(因此不会发送中断或DMA请求)。这是为了避免在清除捕获事件计数器时同时产生更新和捕获中断。
发生更新事件时,所有寄存器都会更新,更新标志(TIMx_SR寄存器中的UIF
位)也会置位(取决于URS
位):
- 重复计数器重新载入TIMx_RCR寄存器的内容
- 预分频器的缓冲器重新载入预载值(TIMx_PSC寄存器的内容)
- 自动重载有效寄存器用预载值(TIMx_ARR寄存器的内容)更新。请注意,自动重载是在计数器重载之前更新的,因此下一个周期是预期的周期。(这句话的意思是说,先更新ARR,再更新CNT)
中心对齐模式(向上/向下计数)
在中心对齐模式下,计数器从0计数到自动重载值(TIMx_ARR寄存器的内容)–1,产生一个计数器溢出事件,然后从自动重载值倒计数到1,并产生一个计数器下溢事件。然后它从0开始重新计数。
当TIMx_CR1寄存器中的CMS
位不等于'00'
时,中心对齐模式生效。输出中配置的通道的输出比较中断标志在以下情况下置位:计数器递减计数(中心对齐模式1,CMS = "01"
),计数器递增计数(中心对齐模式2,CMS = "10"
),计数器递增计数和递减计数(中心对齐模式3,CMS = "11"
)。这里千万别被这个CMS
位的这三种模式误解,虽然有三种模式,但计数器都是交替地向上和向下计数,只是输出比较中断标志什么时候被置位的区别,可以看寄存器手册中的相关定义,如下:
CMS[1:0]: 居中对齐模式选择
00
: 边缘对齐模式。计数器根据方向位(DIR
)递增或递减计数。01
: 居中对齐模式1。计数器交替上下计数。仅当计数器递减计数时,才会设置输出中配置的通道的输出比较中断标志(TIMx_CCMRx寄存器中的CCxS=00
)。10
: 居中对齐模式2。计数器交替上下计数。仅当计数器递增计数时,才会设置输出中配置的通道的输出比较中断标志(TIMx_CCMRx寄存器中的CCxS=00
)。11
: 居中对齐模式3。计数器交替上下计数。计数器递增计数或递减计数时,输出中配置的通道的输出比较中断标志(TIMx_CCMRx寄存器中的CCxS=00
)都会置位。注意:只要计数器使能(
CEN=1
),就不允许从边缘对齐模式切换到中心对齐模式。
在这种模式下,TIMx_CR1寄存器中的DIR方向位不能写入。它由硬件更新并给出计数器的当前方向。
每次计数器上溢和下溢时都会产生更新事件,或者通过设置TIMx_EGR寄存器中的UG
位(通过软件或使用从机模式控制器)也会产生更新事件。这种情况下,计数器从0开始重新计数,预分频器的计数器也是如此。
通过设置TIMx_CR1寄存器的UDIS
位,软件可以禁用UEV更新事件。这是为了避免在预载寄存器中写入新值时更新影子寄存器。那么在UDIS
位被写入0之前,不会发生更新事件。但是,计数器会根据当前的自动重装载值继续上下计数。
此外,如果TIMx_CR1寄存器中的URS
位(更新请求选择)被置位,则置位UG
位会产生UEV
更新事件,但不会置位UIF
标志(因此不会发送中断或DMA请求)。这是为了避免在清除捕获事件计数器时同时产生更新和捕获中断。
发生更新事件时,所有寄存器都会更新,更新标志(TIMx_SR寄存器中的UIF
位)也会置位(取决于URS位):
- 重复计数器重新载入TIMx_RCR寄存器的内容
- 预分频器的缓冲器重新载入预载值(TIMx_PSC寄存器的内容)
- 自动重载有效寄存器用预载值(TIMx_ARR寄存器的内容)更新。请注意,如果更新源是计数器溢出,则自动重装载值会在计数器重新加载之前更新,因此下一个周期就会是预期周期(计数器加载新值)。
图54,计数器时序图,内部时钟除以1,TIMx_ARR = 0x6
图中使用的是中心对齐模式1,UIF仅在计数器递减到1的时候产生中断。且可以看出,计数器是交替上下计数的。