目录
一、TIM介绍
1、TIM简介
2、定时器类型
3、基本定时器
4、通用定时器
5、定时中断基本结构
6、时基单元的时序
(1)预分频器时序
(2)计数器时序
7、RCC时钟树
二、定时器输出比较功能(PWM)
1、PWM波形介绍
2、PWM的基本结构
3、PWM的参数计算
三、定时器输入捕获(测频率和占空比)
1、频率测量
2、主从触发模式
3、输入捕获基本结构
4、PWMI基本结构
四、定时器的编码器接口
1、编码器接口简介
2、正交编码器
3、编码器接口的基本结构
一、TIM介绍
1、TIM简介
TIM(Timer)定时器
定时器的基本功能:定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断。
即定时触发中断,同时也可以看出,定时器就是一个计数器,当这个计数器的输入是一个准确可靠的基准时钟的时候, 那它在对这个基准时钟进行计数的过程,实际上就是计时的过程。
比如在STM32中,定时器的基准时钟一般都是主频72MHz,如果对72MHz计72个数,计1个数的周期那就是1MHz,1/1MHz=0.000001s,也就是1us的时间,如果对72MHz计72000个数,计1个数的周期那就是1KHz,1/1KHz=0.001,也就是1ms的时间。
STM32的定时器拥有16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时,STM32是16位的,因此如果预分频器设置最大,自动重装也设置最大,2的16次方就是65536,即1/(72MHz/65536/65536) = 59.65s。
这里计数器就是用来执行计数定时的一个寄存器,每来一个时钟,计数器加1。
预分频器,可以对计数器的时钟进行分频,让这个计数更加灵活。
自动重装寄存器就是计数的目标值,就是想要计多少个时钟申请中断。
这些寄存器构成了定时器最核心的部分,我们把这一块电路称为时基单元。
STM32的定时器,不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能。
以上功能分为四个部分介绍:
第一部分是定时器中断和内外时钟源选择的功能;
第二部分是输出比较;
第三部分输入捕获和主从触发模式;
第四部分是编码器接口。
文章主要就是介绍第一部分,定时器中断和内外时钟源选择的功能。
STM32的定时器,根据复杂程度和应用场景分为了高级定时器、通用定时器和基本定时器三种类型。
其中高级定时器最复杂,通用定时器中等复杂但最常用,基本定时器最简单,本篇文章主要就是介绍通用定时器。
2、定时器类型
STM32F103C8T6内部拥有的定时器资源是:TIM1、TIM2、TIM3、TIM4,即一个高级定时器,3个通用定时器,没有基本定时器。
不同的芯片型号,拥有的定时器资源是不同的。
3、基本定时器
基本定时器拥有定时中断和主模式触发DAC的功能。
预分频器之前,连接的就是基准计数时钟的输入,由于基本定时器只能选择内部时钟,所以可以直接认为预分频器的输入是由内部时钟过来的,内部时钟的来源是RCC_TIMxCLK,这里的频率值一般都是系统的主频72MHz,所以通向时基单元的计数基准频率就是72MHz。
接下来看下面部分,由三个最重要的寄存器组成,分别是计数器、预分频器、自动重装寄存器,它们构成了最基本的计数计时电路,所以这一块电路就叫做时基单元。
预分频器可以对72MHz的计数时钟进行预分频,比如预分频器写0,那就是不分频,或者说是1分频,这时候输出频率=输入频率=72MHz,如果预分频器写1,那就是2分频,,输出频率=输入频率/2=36MHz,如果预分频写2,就是3分频,输出频率=输入频率/3=24MHz,以此类推,所以预分频器的值和实际的分频系数相差了1,即实际分频系数=预分频器的值+1,这个预分频器是16位的,所以最大值可以写65535,也就是65536分频。
计数器可以对预分频后的计数时钟进行计数,计数时钟每来一个上升沿,计数器的直接就加1,这个计数器也是16位的,所以里面的值可以从0一直加到65535,如果再加,计数器就会回到0重新开始,计数器的值是在计时过程中会不断地自增运行,当自增运行到目标值时,产生中断,那就完成了定时任务。
所以还需要一个存储目标值的寄存器,那就是自动重装寄存器,自动重装寄存器也是16位的,它存的就是我们写入的计数目标,在运行的过程中,计数值不断自增,自动重装值是固定的目标,当计数值等于自动重装时,也就是计时时间到了,那它就会产生一个中断信号,并且清零计数器,计数器自动开始下一次的计数计时。
图里面右下角画的一个向上的折线箭头UI,就代表这里会产生中断信号,像这种计数值等于自动重装值产生的中断,一般称作为“更新中断”,这个更新中断之后就会通往NVIC,我们再配置好NVIC的定时器通道,那定时器的更新中断就能够得到CPU的响应了。
右下角画的向下的箭头U,代表的是会产生一个事件,这里对应的事件就叫做“更新事件”,更新事件不会触发中断,但可以触发内部其他电路的工作。
以上这些,就是定时器定时中断的全部流程了。
4、通用定时器
通用定时器除了基本定时器的功能外,计数器的计数模式就不止向上计数(计数器从0开始,向上自增,计数到重装值,清零同时申请中断)这一种了,还支持向下计数模式和中央对齐模式。
向下计数模式,就是从重装值开始,向下自减,减到0之后,回到重装值同时申请中断,然后继续下一轮,依次循环,这就是向下计数。
中央对齐的计数模式,就是从0开始,先向上自增,计数到重装值,申请中断,然后再向下自减,计数到重装值,再申请中断,然后继续下一轮,依次循环,这就是中央对齐模式。
在中间时基单元的上方,是内外时钟源选择和主从触发模式的结构。
先看内外时钟源选择,对于基本定时器而言,定时只能选择内部时钟,也就是系统频率72MHz,对于通用定时器,时钟源不仅可以选择内部的72MHz时钟,还可以选择外部时钟。
具体包括:
第一个外部时钟就是来自TIMx_ETR引脚上的外部时钟,参考引脚定义表可知,可以看到PA0处有TIM2_CH1_ETR功能,意思是这个TIM2的CH1和ETR都是复用在了PA0引脚位置。 可以在TIM2的ETR引脚,也就是PA0上接一个外部方波时钟,然后配置一下内部的极性选择、边沿检测和预分频电路,再配置一下输入滤波电路,这两块电路可以对外部时钟进行一定的整形,因为是外部引脚的时钟,所以难免会有些毛刺,那这些电路就可以对输入的波形进行滤波,最后,滤波后的信号,兵分两路,上面一路ETRF进入触发控制器,紧跟着就可以选择作为时基单元的时钟了。 如果想在ETR外部引脚提供时钟,或者想对ETR时钟进行计数,把这个定时器当作计数器来用的话,那就可以配置这一路的电路,在STM32中,这一路也叫做“外部时钟模式2”。
除了外部引脚ETR可以提供时钟外,下面还有一路可以提供时钟,就是TRGI(Trigger In),这一路从名字上来看的话,主要作用是用作触发输入来使用的,这个触发输入可以触发定时器的从模式,也可以作为外部时钟来使用,当TRGI当作外部时钟使用时,这一路就叫做“外部时钟模式1”。
具体有哪些外部时钟通过TRGI这一路,首先是ETR引脚的信号,这里ETR引脚的信号既可以通过ETRF上面一路来当作时钟,又可以通过TRGI下面一路来当作时钟,两种情况对于时钟输入而言是等价的,只不过是下面这一路输入会占用触发输入的通道而已。
其次就是ITR信号,这一部分的时钟信号是来自其他定时器,从右边可以看出,这个主模式的输出TRGO可以通向其他定时器,通向其他定时器的时候,就接到了其他定时器的ITR引脚上来了。左边输入的ITR0和ITR3分别来自其他4个定时器的TRGO输出,定时器的ITRx和定时器TIMx的TRGO连接方式如下图所示。
通过这一路,就可以实现定时器级联的功能。比如,可以先初始化TIM3,然后使用主模式把它的更新事件映射到TRGO上,接着再初始化TIM2,这里选择ITR2,对应的就是TIM3的TRGO,然后后面再选择时钟为外部时钟模式1,这样TIM3的更新事件就可以驱动TIM2的时基单元,也就实现了定时器的级联。
最后,还可以选择TI1F_ED信号,这里连接的是下面的输入捕获单元的CH1引脚,也就是从CH1引脚获得时钟,后缀ED(edge)就是边沿的意思,通过TIMx_CH1这一路输入的时钟,上升沿和下降沿均有效,最后这个时钟还可以通过TI1FP1和TI2FP2获得。
在中间时基单元的下方,包含了两块电路,右边一块是输出比较电路,总共有四个通道,分别对应CH1到CH4的引脚,可以用于输出PWM波形、驱动电机;左边一块是输入捕获电路,也是四个通道,可以用于测量输入方波的频率等;中间的一个寄存器是捕获/比较寄存器,是输入捕获和输出比较电路共用的,因为输入捕获和输出比较不能同时使用,所以这里的寄存器是共用的,引脚也是共用的。
5、定时中断基本结构
首先时基单元下方的运行控制,就是控制寄存器的一些位,比如启动停止、向上或向下计数等等,操作这些寄存器就能控制时基单元的运行。
中间黄色块及左边区域,是为时基单元提供时钟的部分,这里可以选择RCC提供的内部时钟,也可以选择ETR引脚提供的外部时钟模式2,还可以选择触发输入,当做外部时钟模式1,对应的有ETR外部时钟、ITRx其他定时器、TIx输入捕获通道,这些就是定时器所有可选的时钟源了。
最后的编码器模式是编码器独用的模式,普通的时钟用不到这个。
时基单元的右边,就是计时时间到,产生更新中断后的信号去向,中断信号会在状态寄存器里置一个中断标志位, 这个标志位会通过中断输出控制,到NVIC申请中断。中断输出控制就是一个中断输出的允许位,如果需要某个中断,才打开允许位。
6、时基单元的时序
(1)预分频器时序
CK_PSC:预分频器的输入时钟,选内部时钟一般是72MHz;
CN_EN:计数器使能,高电平计数器正常运行,低电平计数器停止;
CK_CNT:计数器时钟,它既是预分频器的时钟输出,也是计数器的时钟输入。
计数器未使能时,计数器时钟不运行,使能后,前半段,预分频系数为1,计数器的时钟等于预分频器的时钟,后半段,预分频器系数变为2了,计数器的时钟也变为之前的一半了。
计数器寄存器:在计数器时钟的驱动下,计数器寄存器也跟随时钟的上升沿不断自增。
自动重装值是FC,当计数值计数到和重装值相等时,在下一个时钟来临时,计数值才清零,同时下面产生一个更新事件,这就是一个计数周期的工作流程。
在计数计到一半时,改变了预分频控制寄存器的分频值,这个变化不会立刻生效,而是会等到本次计数周期结束时,产生了更新事件,预分频控制寄存器的值才会被传递到缓冲寄存器里面去,变化才会生效。
预分频计数器:预分频器内部实际上也是靠计数来分频的,当预分频值为0时,计数器就一直为0,直接输出原频率,当预分频器为1时,计数器就0、1、0、1这样计数,再回到0的时候,输出一个脉冲,这样输出频率就是输入频率的2分频,预分频器的值(PSC)和实际的分频系数之间有一个数的偏移,计数器时钟= 72MHz / (预分频器值 + 1)。
(2)计数器时序
CK_INT:内部时钟72MHz
CNT_EN:时钟使能,高电平启动
CK_CNT:计数器时钟,因为分频系数为2,所以这个频率是内部时钟频率的二分之一
计数器寄存器:在计数器时钟每个上升沿时自增
自动重装初值为0036,因此在0036后的一个计数器时钟上升沿处,计数器寄存器清零,计数器溢出,产生一个更新事件脉冲UEV,还会置一个更新中断标志UIF,这个标志位只要置1,就会申请中断,中断响应后,需要在中断程序中手动清零。
计数器溢出频率=72MHz/(预分频器值+1)/(自动重装值+1),溢出时间=1/计数器溢出频率
通过设置ARPE位,就可以选择是否使用预装功能。
计数器无预装时序时
改变自动重装初值为36时,计数器寄存器计到36就会计数器溢出,直接更新事件,开启下一轮计数。
计数器有预装时序时
在计数中途,将自动重装值由F5改成36,在本轮计数目标仍然会是F5,计数器寄存器会计数到F5后,计数器溢出,更新事件,影子寄存器才会将自动重装值由F5改成36,开启下一轮计数的自动重装值才会变成36。
引入影子(缓存)寄存器,是为了让值的变化和更新事件,同步发生,防止在运行途中更改造成错误。
7、RCC时钟树
在程序中主函数之前,程序还会执行一个SystemInit函数,这个函数就是用来配置时钟树的。
图中左边部分都是时钟的产生电路,右边的都是时钟的分配电路,中间的SYSCLK就是系统时钟72MHz。
在时钟产生电路中,有四个震荡源,分别是内部的8MHz高速RC振荡器(HSI RC);外部的4-16MHz高速石英晶体振荡器,也就是晶振(HSE OSC),一般接8MHz;外部的32.768KHz低速晶振(LSE OSC),这个一般是给RTC提供时钟的;最后是内部的40KHz低速RC振荡器(LSI RC),这个可以给看门狗提供时钟。
上面两个高速晶振,是用来提供系统时钟的,AHB、APB2、APB1的时钟都来源于这两个高速晶振,外部的石英振荡器比内部的RC振荡器相对来说更加稳定一些,所以一般都用外部晶振,如果系统简单,而且不需要那么精确的时钟,也可以用内部RC振荡器,这样就可以省下外部晶振的电路。
在SystemInit函数里,ST公司是按下面这样来配置时钟的。首先会启动内部时钟,选择内部8MHz为系统时钟,暂时以内部8MHz的时钟运行,然后再启动外部时钟,配置外部时钟如上图所示,进入PLLXTPRE锁相环进行倍频,8MHz倍频9倍,得到72MHz,等到锁相环输出稳定后,选择锁相环输出为系统时钟,这样就把系统时钟由8MHz切换成了72MHz。
CSS是时钟安全系统,它也是负责切换时钟的,它可以监测外部时钟的运行状态,一但外部时钟失效,它就会自动把外部时钟切换回内部时钟,保证系统时钟的运行,防止程序卡死造成事故。外部时钟和内部时钟时间差了大概10倍左右。
在时钟分配电路中,首先系统时钟72MHz进入AHB总线,AHB总线有一个预分频器,在SystemInit里配置的分配系数是1,因此AHB的时钟就是72MHz,然后进入APB1总线,这里配置的分频系数为2,所以APB1总线的时钟就是36MHz,由下面的电路,时钟频率又乘2,因此APB1总线的时钟也是72MHz,所以无论是高级、通用还是基本定时器,它们的内部基准时钟都是72MHz。
二、定时器输出比较功能(PWM)
输出比较简称OC(Output Compare),输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形。
CNT是计数器,CCR是捕获/比较寄存器,当CCR为比较寄存器时,CNT计数自增的值会与CCR中的给定值相比较,当CNT的值小于、等于或大于CCR中给定值时,CCR就会输出对应的置1、置0、置1、置0,这样就可以输出一个电平不断跳变的PWM波形,这就是输出比较的基本功能。
每个高级定时器和通用定时器都拥有4个输出比较通道,但是它们是共用一个CNT计数器的。
1、PWM波形介绍
脉冲宽度调制简称PWM(Pulse Width Modulation),在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,即通过输入数字量,来得到输出模拟量,常应用于电机控速等领域。
PWM参数
T_S:周期,T_ON:高电平,T_OFF:低电平
频率 = 1 / T_S 占空比 = T_ON / T_S
分辨率 = 占空比变化步距(分辨率为1%,则占空比按1%、2%、3%变化)
输出比较的8个模式
其中有效电平就是指高电平,无效电平就是指低电平。
这里主要使用PWM模式1中的向上计数。
2、PWM的基本结构
PWM初始化配置
(1)RCC开启TIM外设和GPIO的时钟;
(2)配置时钟源;
(3)配置时基单元;
(4)配置输出比较单元,包括CCR的值,输出比较模式、极性选择和输出使能;
(5)配置GPIO口,把PWM对应的GPIO口,初始化为复用推挽输出;
(6)运行控制,启动计数器。
配置好时基单元后,CNT就会不断自增运行,CCR是给定值,CNT和CCR会不断比较,后面的输出模式控制器采用PWM模式1,向上计数方式。
当CNT<CCR时,REF参考值输出高电平;当CNT≥CCR时,REF参考值输出低电平。
上图中,黄色线是ARR自动重装器的值,蓝色线是CNT计数器不断自增的值,红色线是CCR中给定值。
假设给ARR=99,CCR=30时,当CNT=0~29,输出高电平给GPIO;当CNT=30~99,输出低电平给GPIO。这样就能通过这三个寄存器的值来调控PWM的频率和占空比了。
3、PWM的参数计算
PWM频率: Freq = CK_PSC / (PSC + 1) / (ARR + 1)
PWM占空比: Duty = CCR / (ARR + 1)
PWM分辨率: Reso = 1 / (ARR + 1)
CK_PSC:预分频器的输入时钟,选内部时钟一般是72MHz;
PSC:预分频器的值
ARR:自动重装器的值
CCR:比较器的值
三、定时器输入捕获(测频率和占空比)
输入捕获简称IC(Input Capture),输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT(计数器)的值将被锁存到CCR(捕获寄存器)中,可用于测量PWM波形的频率(脉冲间隔)、占空比(电平持续时间)等参数。
每个高级定时器和通用定时器都拥有4个输入捕获通道。
可配置为PWMI模式,同时测量频率和占空比;
可配合主从触发模式,实现硬件全自动测量(在CNT值存到CCR中后,将CNT清零)。
1、频率测量
测频法(适合测量高频信号):在闸门时间T内,对上升沿计次,得到N,则频率:
测周法(适合测量低频信号):两个上升沿内,以标准频率fc计次,得到N ,则频率:
中界频率:测频法与测周法误差相等的频率点:
当信号频率大于中界频率时,采用测频法;当信号频率小于中界频率时,采用测周法。
本次实验测量PWM信号的频率和占空比采用的是测周法。
上升沿用于触发输出捕获,CNT用于计数计时,每来一个上升沿,就取CNT的值,自动存在CCR里, CCR捕获到的值就是计次N,CNT的驱动时钟就是标准频率fc(72M/预分频系数),通过fc/N就能得到信号频率。
每次捕获CNT的值存在CCR中后,都要将CNT清零,这样下次上升沿再捕获的时候,取出的CNT才是两个上升沿的时间间隔。
2、主从触发模式
主从触发模式:为主模式、从模式和触发源选择三个模式的简称。
主模式可以将定时器内部的信号,映射到TRGO引脚,用于触发别的外设;
从模式就是接收其他外设或者自身外设的一些信号,用于控制自身定时器的运行,也就是被别的信号所控制;
触发源选择就是选择从模式的触发信号源,选择指定的一个信号,得到TRGI去触发从模式,然后从模式就可以在列表中选择一项来自动执行,也可以认为触发源选择是从模式的一部分。
因此为了使捕获CNT的值存在CCR中后,将CNT清零操作,触发源选择TI1FP1,然后从模式执行的操作选择Reset,这样TI1FP1的信号就可以自动触发从模式,从模式自动清零CNT。
3、输入捕获基本结构
这里只使用了一个输入捕获通道,只能测量频率。
首先将右上角的时基单元配置好,启动定时器,CNT就会开始自增。
从GPIO会输入一个左上角的方波信号,经过滤波器和边沿检测,选择TIFP1为上升沿触发,之后输入选择直连的通道,分频器选择不分频,当TIFP1出现上升沿时,CNT的当前计数值存到CCR1里;之后触发源选择,选中TIFP1为触发信号,从模式选择复位操作,这样TIFP1的上升沿就会通过上面的Reset去触发CNT清零。
计算信号频率:f=标准频率fc(72M/预分频系数)/N(CCR)
4、PWMI基本结构
PWMI模式使用两个通道同时捕获一个引脚,可以同时测量周期和占空比。
TI1FP1配置上升沿触发,触发捕获和清零CNT;
TI1FP2配置下降沿触发,通过交叉通道,去触发通道2的捕获单元。
如左上角图所示,第一个上升沿是TI1FP1触发上升沿,将CNT值存在CCR1中,之后CNT清零;第一个下降沿,就是TI1FP2触发,将这时的CNT值存到CCR2中,这里的CNT值就是高电平期间的计数值,并不触发CNT清零。
所以CCR2就是高电平期间的计数值,CCR1就是一整个周期的计数值。
占空比=CCR2/CCR1
输入捕获模式初始化配置:
(1)RCC开启时钟,将TIM和GPIO的时钟打开;
(2)GPIO初始化,把GPIO配置成输入模式,一般选择上拉输入或浮空输入;
(3)配置时基单元,让CNT计数器在内部时钟的驱动下自增运行;
(4)配置输入捕获单元,包括滤波器、极性、直连通道还是交叉通道、分频器这些参数;
(5)选择从模式的触发源,触发源选择为TI1FP1;
(6)选择触发之后的操作,执行Reset操作;
(7)调用TIM_Cmd函数,开启定时器。
四、定时器的编码器接口
触发外部中断手动计次(5-2程序):当电机高速旋转时,每秒产生成千上万个脉冲,程序就得频繁中断,进中断后,完成的任务又只是简单得加1减1,软件资源就会被简单又低级的工作占用了,所以对于需要频繁执行,操作又比较简单的任务,一般都会设计一个硬件电路模块来自动完成。因此采用定时器的编码器接口自动计次(6-8程序),会更好的利用软件资源。
1、编码器接口简介
编码器接口(Encoder Interface),可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度。
每个高级定时器和通用定时器都拥有1个编码器接口,两个输入引脚借用了输入捕获的通道1和通道2。
2、正交编码器
当编码器的旋转轴转起来时,A相和B相就会输出上图所示的方波信号给STM32,转的越快,这个方波的频率就越高,所以频率就代表了速度,取出任意相的信号来测频率,就能得到旋转速度。但是只有一相的信号时,无法测出旋转方向。
编码器接口的设计逻辑
首先把A相和B相的所有边沿作为计数器的计数时钟,出现边沿信号时,就计数自增或自减,具体是增还是减就需要靠另一项状态来决定。当出现某个边沿时,判断另一相的高低电平,如果另一项状态为上表中,则判断为正传,计数自增;反之,当出现某个边沿时,另一项的状态符合下表,则判断为反转,计数自减。
TI1FP1对应A相,TI1FP2对应B相。相对信号的电平对应另一相的高低电平。
向上计数意思就是正传,向下计数意思就是反转。
仅在T1计数,意思是只在A相上升沿和下降沿的时候计数,不考虑B相;
仅在T2计数,意思是只在B相上升沿和下降沿的时候计数,不考虑A相;
在T1和T2计数,意思是同时考虑A相和B相的上升沿和下降沿时候计数。**(一般使用这个模式,精度最高)**
采用在T1和T2同时计数时,下面是实例(均不反相)。
中间的毛刺就是噪声,通过检测A相和B相两个方波信号,可以滤掉噪声。
采用在T1和T2同时计数时,下面是实例(反相)。
这里的TI1信号是反相的,需要将TI1高低电平取反之后,查表才是正确的。
如果接一个编码器,发现数据的加减方向反了,这时候就可以调整以下极性,把任意一个引脚反相,就能反转计数方向了,或者也可以将A相和B相的引脚换一下,也可以改变极性。
3、编码器接口的基本结构
(1)RCC开启时钟,开启GPIO和定时器时钟;
(2)配置GPIO口,需要把PA6和PA7配置成输入模式;
(3)配置时基单元,预分频器一般选择不分频,自动重装其ARR一般给最大值65535,只需要CNT执行计数就可以了;
(4)配置输入捕获单元,只有滤波器和极性两个参数有用到;
(5)配置编码器接口模式;
(6)启动定时器。