🐱作者:一只大喵咪1201
🐱专栏:《STM32学习》
🔥格言:你只管努力,剩下的交给时间!
STM32F1 的通用定时器是一个通过可编程预分频器(PSC)驱动的 16 位自动装载计数器(CNT)构成。 STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。
使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。
STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。
STM3F1 的通用 TIMx (TIM2、 TIM3、 TIM4 和 TIM5)定时器特点包括:
- 位于低速的APB1总线上
- 16 位向上、向下、向上/向下自动装载计数器(TIMx_CNT)。
- 16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~65535 之间的任意数值。
- 4 个独立通道(TIMx_CH1~4),这些通道可以用来作为:
A.输入捕获
B.输出比较
C. PWM 生成(边缘或中间对齐模式)
D.单脉冲模式输出- 可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。
- 如下事件发生时产生中断/DMA:
A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
C.输入捕获
D.输出比较
E.支持针对定位的增量(正交)编码器和霍尔传感器电路
F.触发输入作为外部时钟或者按周期的电流管理
通用定时器占了4个,还有4个分别是俩个高级定时器(TIM1和TIM8),俩个基本定时器(TIM5和TIM6),它们各自的功能有所区别
这是通用定时器的工作框图,下面本喵将其分为几个部分讲解。
时基单元包括:
它在框图中的
这个位置。
该寄存器是一个16位的寄存器
它的计数范围就是1~65535,超出这个范围就会发生溢出。
计数器由预分频器的时钟输出CK_CNT驱动,仅当设置了计数器TIMx_CR1寄存器中的计数器使能位(CEN)时, CK_CNT才有效。
也就是控制寄存器CR1中的位0相当于时钟CK_CNT的开关,只有它使能也就是值位1的情况下CK_CNT才会驱动CNT寄存器进行计数。
它在框图中的
这个位置。
该寄存器同样是一个16位的寄存器,
它能存放值是范围也是1~65535,它的作用就是将驱动定时器的时钟(图中的CK_PSC)进行分频,该寄存器中的值是多少,就将CK_PSC的时钟进行(PSC[15:0]+1)的分频。至于为什么是加1,是因为预分频计数器是从0开始计数的。
它是基于一个(在TIMx_PSC寄存器中的)16位寄存器控制的16位计数器,这个控制寄存器带有缓冲器,它能够在工作时被改变。新的预分频器参数在下一次更新事件到来时被采用。
PSC的分频系数会在它的值的基础上加1,所以将它的值由0改为1,也就是将分频系数由1改到2。由时许图中可以清除的看到,在更新事件产生以后,CNT计数器计数的频率改变了。
预分频计数器中的值此时也从0加到1,然后再到0,如此往复循环,控制着CK_CNT的频率。
它在框图中的
这个位置。
该寄存器同样是一个16位的寄存器
它能存放值是范围也是1~65535,它作用就是给计数器寄存器CNT设置一个参照,CNT中的计数值总是在和ARR中的值比较。
自动装载寄存器是预先装载的,写或读自动重装载寄存器将访问预装载寄存器。根据在TIMx_CR1寄存器中的自动装载预装载使能位(ARPE)的设置,预装载寄存器的内容被立即或在每次的更新事件UEV时传送到影子寄存器。
当计数器达到溢出条件(向下计数时的下溢条件)并当TIMx_CR1寄存器中的UDIS位等于’0’时,产生更新事件。更新事件也可以由软件产生。
在框图中可以看到,自动重装载寄存器ARR的后面是有影子的,这个影子也是一个寄存器,就叫做影子寄存器。
自动重装载器中的值是影子寄存器给它的,我们都是通过修改影子寄存器中的值,然后影子寄存器再将值给到ARR寄存器中才实现设置计数值的目的的。
将控制寄存器CR1的位7,也就是ARPE位
使能以后,就相当于打开了影子寄存器。
影子寄存器打开和关闭的区别:
- 打开:当我们在定时器工作的过程中修改了ARR寄存器中的值后,寄存器ARR中的值不会立马改变,而是在每次的更新事件(UEV)时,将改变后的值传送到影子寄存器,进而改变ARR中的值,也就是改变值的时候是有一个缓冲的。
UEV是否被允许由CR1寄存器的位1控制。- 关闭:当我们在定时器工作的过程中修改了ARR寄存器中的值后,会立刻将改变的值传送到影子寄存器,立刻改变ARR中的值,也就是改变值的时候是没有缓冲的
在ARPE位为0的时候,ARR中的值从0XFF改变为0X36以后,计数器CNT在计数到36以后就产生了计数器溢出,产生更新事件,发生更新中断。
在ARPE位为0的时候,ARR中的值从0XF5改变为0X36以后,计数器仍然是在计数到0XF5以后才产生计数器溢出,并没有立刻改变。在计数到0XF5后产生了更新事件后,改变后的值0X36才被传送到影子寄存器,也就是才放在了ARR中,下一次CNT计数到0X36就会产生溢出事件。
它在框图的
这个位置。
计数模式有三种:
在向上计数模式中,计数器从0计数到自动加载值(TIMx_ARR计数器的内容),然后重新从0开始计数并且产生一个计数器溢出事件。
每次计数器溢出时可以产生更新事件(UEV),在TIMx_EGR寄存器中(通过软件方式或者使用从模式控制器)设置UG位也同样可以产生一个更新事件。
将该位由软件置1后,并且中断是开启,就可以强制进入中断服务程序。
内部时钟分频因子不一样时,计数的频率也会不一样。
下图是当TIMx_ARR=0x36时计数器在不同时钟频率下的动作。
内部时钟分频因子是1的时候,时钟CK_CNT的频率和内部时钟CK_INT的一样。
内部时钟分频因子是2的时候,时钟CK_CNT的频率是CK_INT的一半。
在向下模式中,计数器从自动装入的值(TIMx_ARR计数器的值)开始向下计数到0,然后从自动装入的值重新开始并且产生一个计数器向下溢出事件。每次计数器溢出时可以产生更新事件,TIMx_EGR寄存器中(通过软件方式或者使用从模式控制器)设置UG位,也同样可以产生一个更新事件。
只是计数的方向不一样,其他都和向上计数模式一样。
在中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−1,产生一个计数器
溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。在这个模式,不能写入TIMx_CR1中的DIR方向位。它由硬件更新并指示当前的计数方向。
此时CR1寄存器中的位4,DIR位是不能用来设置计数方向的,只能由读取现在是处于哪个计数方向。
该模式和前俩种模式在时序图上的区别就是,CNT计数到ARR值后不变0,而是从ARR开始继续向下计数。
这是3种模式下CNT计数器寄存器中的值与时间之间的关系曲线,ARR中的值就是参照。
时钟源有4个:
这是我们最常用的时钟源,绝大多数情况下使用的都是内部时钟源(CK_INT)。
这是它在框图中的路线。
如果禁止了从模式控制器(TIMx_SMCR寄存器的SMS=000),则CEN、 DIR(TIMx_CR1寄存器)和UG位(TIMx_EGR寄存器)是事实上的控制位,并且只能被软件修改(UG位仍被自动清除)。只要CEN位被写成’1’,预分频器的时钟就由内部时钟CK_INT提供。
SMCR位我们很少用到,本喵不再介绍,其余CEN、DIR、UG位前面都介绍过,我们直接看时序图。
内部时钟CK_INT是来源于RCC的TIMx的,然后CK_INT经过从模式寄存器处理后给CK_PSC提供时钟源,CK_PSC经过预分频寄存器PSC分频后给CK_CNT提供时钟源,所以在CEN使能以后,内部时钟进行了俩个时钟周期,CK_CNT才有了时钟信号。
其他三种模式,由于用到的比较少,在涉及到的时候本喵会详细讲解。
每个通用寄存器都有4个通道,这个4个通道既能输入捕获也能输出比较。
每一个捕获/比较通道都是围绕着一个捕获/比较寄存器(包含影子寄存器),包括捕获的输入部分(数字滤波、多路复用和预分频器),和输出部分(比较器和输出控制)。
捕获过程:
通过设置CCMR1寄存器中的CC1S位来设置通道的工作模式。只要不是00,就是输入捕获模式。
假设从TI1输入一个信号,我们想捕获它的上升沿,该信号我们知道它最多在5个内部时钟(CK_INT)周期内发生抖动,这些抖都可能会造成误捕获。所以通样以内部时钟(CK_INT)的频率连续采用8次,如果这8次都是高,说明我们捕获的信号是正确的,这样就可以过滤一些信号,所以也叫做滤波器。
需要将CCMR1寄存器中的
位IC1F设置成0011。
如此一来滤波这一步就完成了,该信号被记作TI1F。
通过将CCER寄存器中的CC1P设为0,此时只有输入信号是高电平的时候才会捕获。此时边缘检测器也设置好了。
此时的TI1FP1不仅有一个去向,他可以映射到IC1上,也可以映射到其他通道,体现在图中的红色圈上。
这一位我们在前面讲解过。
通设置CCMR1寄存器中的IC1PSC1设置预分频系数
也就是可以设置被捕获信号产生了几次会产生一次捕获事件,就比如捕获高电平,通过我们前面一系列设置后的信号,产生了几次高电平后会触发一次捕获事件。
当捕获使能以后,发生捕获事件时,计数器CNT中的值就会被传送到寄存器CRR1中
通过该值,我们就可以计算出捕获信号的频率等。
如果开启了中断,在发生捕获事件时就会进入捕获中断,执行中断服务函数。
输出比较是框图中的这一部分。
此项功能是用来控制一个输出波形,或者指示一段给定的的时间已经到时。
输出比较模式的配置步骤:
通常都是选择内部时钟(CK_INT)作为时钟源的。
ARR的值仍然是计数器CNT产生溢出事件的一个参考值,CRR是发生反转的参考值。
如上图,当计数器CNT中的值小于CRR中的参考值时,IO口输出的是低电平,当计数器CNT中的值大于CRR中的值并且小于ARR的值的时候,IO输出的是高电平。当然,具体是高电平和低电平是可以设置的。
此时
捕获/比较寄存器就设置好了。
模式的选择需要配置的是CCMR1寄存器中的OC1M,具体要配置什么模式,在使用的时候本喵进行详细讲解。
至此,输出控制部分就配置完了
TIMx_CCRx寄存器能够在任何时候通过软件进行更新以控制输出波形,条件是未使用预装载寄
存器(OCxPE=’0’,否则TIMx_CCRx影子寄存器只能在发生下一次更新事件时被更新)。
计数器CNT中的值一旦和CCR中的值匹配,IO口的电平状态就会发生一次反转。
是不是感觉很枯燥乏味?这篇文章一直都是在讲解通用定时器的原理,以及一些重要寄存器的配置。在后面本喵会介绍通用定时器具体使用的实验,这篇原理的介绍也是在为我们使用奠定一个基础。希望对大家有所帮助。