【TIM定时器】定时中断/外部时钟
CSS(Clock Security System)时钟安全系统:也可以切换时钟,可以监测外部时钟运行状态,一旦外部时钟失效,CSS就会自动把外部时钟切换回内部时钟,保证系统时钟的运行,防止程序卡死造成事故。在运行的过程中,计数值不断自增,而自动重装值是固定的目标,当计数值==自动重装值时,说明计时时间到——进而产生一个中断信号,并且清零CNT计数器,CNT计数器再自动开始下一次的计数计时。在计数
·
一、TIM简介
-
定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断
-
16 位计数器、预分频器、自动重装寄存器的时基单元,在 72MHz 计数时钟下可以实现最大 59.65s 的定时
-
不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
-
根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型
二、定时器类型

STM32F103C8T6 定时器资源: TIM1 、 TIM2 、 TIM3 、 TIM4
三、定时器结构
基本定时器

预分频器对时钟进行预分频,计数器自增计数,当计数值计到自动重装值时,计数值清零同时产生更新中断和更新事件
1)PSC预分频器、CNT计数器、自动重装载寄存器构成最基本的计数计时电路——时基单元
2)基本定时器只能选择内部时钟,内部时钟的来源是RCC_TIMxCLK,频率值一般为系统的主频72MHz
-
PSC预分频器(16位):对输入的基准频率提前进行分频的操作(对72MHz的计数时钟进行预分频)
ex:PSC预分频寄存器写0——1分频,输出频率=输入频率=72MHz
PSC预分频寄存器写1——2分频,输出频率=输入频率=72MHz/2=36MHz
PSC预分频寄存器写2——3分频,输出频率=输入频率=72MHz/3=24MHz
以此类推………
预分频器是16位的,最大值可以写65535,最大实际分频系数也就是65535+1=65536
总结:PSC预分频寄存器与实际分频系数相差了1
即实际分频系数=预分频器的值+1
-
CNT计数器(16位):对预分频后的计数时钟进行计数,计数时钟每来一个上升沿,计数器的值就加1
CNT计数器是16位的,因此里面的值可以从0一直加到65535,再加的话计数器将回到0重新开始
-
计数方式:向上计数
计数器的值在计时过程中会不断地自增运行,当自增运行到目标值时产生中断,完成定时任务

-
自动重装载寄存器(16位):存储计数目标值的寄存器
在运行的过程中,计数值不断自增,而自动重装值是固定的目标,当计数值==自动重装值时,说明计时时间到——进而产生一个中断信号,并且清零CNT计数器,CNT计数器再自动开始下一次的计数计时

计数值==自动重装值而产生的中断称为【更新中断】
通用定时器

通用定时器和高级定时器支持向上计数模式、向下计数模式、中央对齐模式

向上计数模式最常用
【内外时钟源选择结构、主从触发模式结构】

对于基本定时器而言,定时只能选择内部时钟==系统频率72MHz
而通用定时器的时钟源不仅可以选择内部的72MHz时钟,还可以选择外部时钟
外部时钟
-
【外部时钟模式2】
TIMx_ETR引脚上的外部时钟(ETR:External)
如果想用ETR外部引脚提供时钟,或者想对ETR时钟进行计数,把这个定时器当作计数器使用的话,就可以选择配置此电路

ETR引脚的位置可以参考芯片引脚定义表(STM32F103C8T6中ETR复用在了PA0引脚)
-
在TIM2的ETR引脚(PA0)上接一个外部方波时钟,经过【极性选择、边沿检测和预分频器】和配置【输入滤波】电路对外部时钟进行整形(外部引脚的时钟会有毛刺)
-
滤波后的信号兵分两路,上面一路【ETRF】进入触发控制器,可以被选择作为下面时基单元的时钟了

-
【外部时钟模式1】
1)同样来自ETR引脚,下面一路也提供时钟,就是【TRGI】(Trigger In)
-
主要用作触发输入使用,可以触发定时器的从模式
-
这个触发输入也可作为外部时钟使用,把【TRGI】当做外部时钟的输入来看
与ETRF时钟输入等价,只是TRGI时钟输入会占用触发输入的通道
2)ITR信号
这一部分的时钟信号来自其他定时器
主模式的输出【TRGO】通向其他定时器,即通向其他另外定时器的【ITR】引脚上
-
【ITR0~ITR3】分别来自其他4个定时器的【TRGO】输出
-
具体连接方式参考手册

通过这一路可以实现定时器级联的功能
3)TI1F_ED作为外部时钟输入(CH1引脚的边沿)

后缀_ED==边沿(Edge)————也就是通过这一路输入的时钟,上升沿和下降沿均有效
TI1F_ED连接的是输入捕获单元的【CH1】引脚,也就是从【CH1】引脚获得时钟
4)TI1FP1和TI2FP2作为外部时钟输入(CH1引脚和CH2引脚)

-
一般情况下外部时钟通过1)ETR引脚就可以了
-
2)3)4)设置的输入不仅为了扩大时钟输入范围,更是为某些特殊应用场景设计的

左边:输入捕获电路,总共有四个通道,分别对应CH1到CH4的引脚——用于测量输入方波的频率等
中间:捕获/比较寄存器,是输入捕获和输出比较电路共用的
右边:输出比较电路,总共有四个通道,分别对应CH1到CH4的引脚——用于输出PWM波形,驱动电机
//输入捕获和输出比较不能同时使用,所以中间的寄存器是共用的,引脚也是共用的
高级定时器

高级定时器相比于通用定时器主要的改动是增加了右边这几个部分
-
申请中断的地方,增加了一个重复次数计数器

加上重复次数计数器后可以实现 每隔几个计数周期才发生一次更新事件和更新中断==对输出的更新信号又做了一次分频
//原来的结构: 每个计数周期完成后都会发生更新
-
增加了DTG(Dead Time Generate):死区生成电路
-
右边的输出引脚由原来的一个变为了两个互补的输出,可以输出一对互补的PWM波
-
这一部分是为了驱动三相无刷电机的, 三相无刷电机的驱动电路一般需要3个桥臂,每个桥臂由2个大功率开关管控制,总共需要6个大功率开关管控制————因此输出PWM引脚的前三路变为了互补的输出,第四路不用变化(前三路就够了)

-
增加刹车输入功能:给电机驱动提供安全保障
-
如果外部引脚BKIN(Break In)产生了刹车信号,或者内部时钟失效产生了故障,那么此控制电路就会自动切断电机的输出,防止意外的发生

四、定时中断基本结构图

五、预分频器时序
参考

CK_PSC:预分频器的输入时钟
CNT_EN:计数器使能(高电平计数器运行,低电平计数器停止)
CK_CNT:计数器时钟,既是预分频器的时钟输出,也是计数器的时钟输入
当预分频器的参数从1变到2时,计数器的时序图

一个计数周期的工作流程:
-
开始时,计数器未使能,计数器时钟不运行
-
使能后前半段预分频系数为1,计数器时钟等于预分频器前时钟;后半段预分频系数变为2,计数器时钟等于预分频器前时钟一半
-
在计数器时钟的驱动下,下面的计数器寄存器跟着时钟的上升沿不断自增——当增加到FC之后计数器寄存器的值变为0, 可以推断出ARR自动重装值为FC(当计数值计到和重装值相等,并且下一个时钟来临时,计数值清零)
-
计数值清零后,产生一个更新事件
下面的三行时序: 预分频寄存器的一种缓冲机制

实际上预分频寄存器有两个
-
预分频控制寄存器:供我们读写,它并不直接决定分频系数
-
预分频缓冲器(缓冲寄存器)(影子寄存器):真正起作用的寄存器
ex:在某个时刻把预分频控制寄存器由0改成了1,如果此时立刻改变时钟的分频系数,将会导致在一个计数周期内,前半部分和后半部分的频率不一样,也就是计数计到一半,计数频率突然发生改变
ST公司为了严谨,设计了预分频缓冲器——在计数时改变了分频值,这个变化并不会立刻生效,而是等到本次计数周期结束时,产生了更新事件后,预分频控制寄存器的值才会被传递到预分频缓冲器中并生效
-
预分频计数器:预分频器内部实际上也是靠计数来分频的,当预分频值为0时(预分频系数为1),预分频计数器就一直为0,直接输出原频率 ;当预分频值为1时(预分频系数为2),预分频计数器就01010101这样计数,在回到0的时候输出一个脉冲,这样输出频率就是输入频率的2分频
计数器计数频率:CK_CNT = CK_PSC/(PSC + 1)
六、计数器时序
参考

CK_INT:内部时钟(72MHz)
CNT_EN:计数器使能(高电平计数器运行,低电平计数器停止)
CK_CNT:计数器时钟,既是预分频器的时钟输出,也是计数器的时钟输入
内部时钟分频因子为2(分频系数为2)

计数器的工作流程:
-
开始时,计数器未使能,计数器时钟不运行
-
预分频系数为2,计数器时钟等于预分频器前时钟一半
-
在计数器时钟的驱动下,下面的计数器寄存器跟着时钟的上升沿不断自增——当增加到0036之后计数器寄存器的值变为0, 可以推断出ARR自动重装值为0036
-
当计数值计到和重装值相等,再来一个上升沿, 计数值清零, 计数器溢出,产生一个更新事件脉冲
-
还会置一个更新中断标志位【UIF】,只要【UIF】置1就会申请中断,在中断响应后,需要在中断程序中手动清零
计数器溢出频率:CK_CNT_OV = CK_CNT /(ARR + 1)= 【CK_PSC /(PSC + 1)】/ (ARR + 1)//用【72MHz / ( PSC + 1 )】/ ( ARR + 1 )就能得到溢出频率//溢出时间=1/溢出频率EX:得到1hz的溢出频率,可设置PSC和ARR为?溢出频率=[72M/(PSC+1)]/(ARR+1)]=[72000000/(7200)]/(10000)=10000/10000=1hz得:PSC设置为7200 - 1;ARR设置为10000 - 1//溢出时间=1 / 1hz = 1S
//【预分频器】为了防止计数中途更改数值造成错误而设计了预分频缓冲器(缓冲寄存器)(影子寄存器)
很多寄存器都有影子寄存器这样的缓冲机制,包括【预分频器】、【自动重装寄存器】、【捕获/比较寄存器】
七、ARR自动重装寄存器【缓冲寄存器】
-
缓冲寄存器可以设置为用或不用(通过设置ARPE位可以选择是否使用预装功能)
计数器无预装时序(无缓冲寄存器)

-
计数器使能后进行自增计数,此时更改自动重装寄存器(由FF改为了36),那么计数值的目标值就由FF变成了36
-
当计数器寄存器自增到36时,就产生中断,直接更新,开始下一轮计数
计数器有预装时序(有缓冲寄存器)

-
计数器使能后进行自增计数,此时更改自动重装寄存器(由F5改为了36),那么计数值的目标值就由F5变成了36
-
因为有缓冲寄存器,所以当前还是之前自动重装寄存器的计数目标F5,到自增到F5时产生更新事件,同时再把要更改的36传递到缓冲寄存器,在下一个计数周期这个更改的36才有效
-
当计数器寄存器自增到36时,就产生中断,直接更新,开始下一轮计数
八、RCC时钟树

时钟树:STM32中用来产生和配置时钟,并且把配置好的时钟发送到各个外设的系统
时钟时所有外设运行的基础,所以时钟也是最先需要配置的东西
//时钟产生电路//

-
时钟产生电路有4个振荡源
1、内部的8MHz高速RC振荡器
2、外部的 4—16MHz高速石英晶体振荡器(晶振),一般接8MHz
3、外部的32.768KHz低速晶振,一般是给RTC提供时钟的
4、内部的40KHz低速RC振荡器,可以给看门狗提供时钟
1、2高速晶振用来提供系统时钟(AHB、APB1、APB2时钟),外部的晶振比内部的RC振荡器更稳定,所以一般用外部晶振
如果系统很简单而且不需要那么精确的时钟,可以使用内部RC振荡器
在SystemInit函数里,ST配置时钟流程:
1、启动内部时钟,选择内部8MHz为系统时钟,暂时以内部8MHz的时钟运行
2、启动外部时钟,进入PLL锁相环进行【倍频】,将外部时钟8MHz倍频9倍得到72MHz
3、等到锁相环输出稳定后,选择锁相环输出为系统时钟
4、这样就把系统时钟由内部8MHz切换为了72MHz
-
CSS(Clock Security System)时钟安全系统:也可以切换时钟,可以监测外部时钟运行状态,一旦外部时钟失效,CSS就会自动把外部时钟切换回内部时钟,保证系统时钟的运行,防止程序卡死造成事故
//时钟分配电路//

-
首先系统时钟72MHz进入AHB总线,AHB总线的预分频器在SystemInit里配置的分频系数为1,则AHB的时钟为72MHz
-
然后进入APB1总线,此处预分频器配置的分频系数为2,APB1外设时钟为最大36MHz
-
(此处走下面的支路使通向定时器2~7的时钟变为72MHz)
-
-
然后进入APB2总线,此处预分频器配置的分频系数为1
-
(此处走下面的支路使通向定时器1~8的时钟变为72MHz)
-
//时钟输出有一个与门进行输出控制,控制位写的是外部时钟使能(这就是在程序中写RCC_APBxPeriphClockCmd作用的地方)
打开时钟就是在这个位置写1,让左边的时钟能够通过与门输出给外设
更多推荐
所有评论(0)