一.定时器详解
1.定时器分类
二.基本定时器TIM6,TM7
1.基本定时器功能框图(时基)
1.1 时钟源
定时器时钟 TIMxCLK ,即内部时钟 CK_INT ,经 APB1 预分频器后分频提供,如果 APB1 预分频系数等于1 ,则频率不变,否则频率乘以 2 ,库函数中 APB1 预分频的系数 即 PCLK1=36M ,所以定时器时钟TIMxCLK=36*2=72M 。
详见如图
1.2计数器时钟
定时器时钟经过 PSC 预分频器之后,即 CK_CNT ,用来驱动计数器计数。 PSC 是一个 16 位的预分频器,可以对定时器时钟TIMxCLK 进行 1~65536 之间的任何一个数进行分频。具体计算方式为: CK_CNT=TIMxCLK/(PSC+1) 。加1的原因是由于起始值是从0开始的。
1.3 计数器
计数器 CNT 是一个 16位的计数器 , 只能往上计数 ,最大计数值为 65535 。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。
1.4 自动重装载寄存器ARR
自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候, 如果使能了中断的话,定时器就产生溢出中断。
1.5 定时时间的计算
定时器的定时时间等于计数器的中断周期乘以中断的次数。 计数器在CK_CNT的驱动下 ,计一个数的时间则是CK_clk 的倒数,等于: 1/ ( TIMxCLK/(PSC+1) ),产生一次中断的时间则等于:1/( CK_CLK*ARR )。如果在中断服务程序里面设置一个变量 time ,用来记录中断的次数,那么就可以计算出我们需要的定时时间等于:1/CK_CLK*(ARR+1)*time 。总结定时时间为72000000/(PSC+1)=CK_CNT, tiime = (1/CK_CNT)*(ARR+1)
2.定时器初始化结构体(时基部分初始化不仅仅使用于基本定时器,所有的定时器都需要用到该部分)
2.1 结构体代码如下
typedefstruct{
uint16_tTIM_Prescaler; //预分频器
uint16_tTIM_CounterMode; //计数模式
uint32_tTIM_Period; //定时器周期
uint16_tTIM_ClockDivision; //时钟分频
uint8_tTIM_RepetitionCounter; //重复计算器
} TIM_TimeBaseInitTypeDef;
(1)TIM_Prescaler :定时器预分频器设置,时钟源经该预分频器才是定时器时钟,它设定 TIMx_PSC寄存器的值。可设置范围为0 至 65535 ,实现 1 至 65536 分频。(2)TIM_CounterMode :定时器计数方式,可是在为向上计数、向下计数以及三种中心对齐模式。基本定时器只能是向上计数,即TIMx_CNT 只能从 0 开始递增,并且无需初始化。(3)TIM_Period(ARR) :定时器周期,实际就是设定自动重载寄存器的值,在事件生成时更新到影子寄存器。可设置范围为0 至 65535 。(4)TIM_ClockDivision :时钟分频,设置定时器时钟 CK_INT 频率与数字滤波器采样时钟频率分频比,基本定时器没有此功能,不用设置。(5)TIM_RepetitionCounter :重复计数器,属于高级控制寄存器专用寄存器位,利用它可以非常容易控制输出PWM 的个数。这里不用设置。
3.程序配置步骤
1)
开定时器时钟
TIMx_CLK,x[6,7]
;
(2)
初始化时基初始化结构体;
(3)
使能
TIMx,x[6,7]update
中断;
(4)
打开定时器;
(5)
编写中断服务程序
通用定时器和高级定时器的定时编程要点跟基本定时器差不多,只是还要再选择下计数器的计
数模式,是向上还是向下。因为基本定时器只能向上计数,且没有配置计数模式的寄存器,默认
是向上。
三. 高级定时器和通用定时器
1.高级定时器
1.1 功能框图
1.2 时钟源
高级控制定时器有四个时钟源可选:• 内部时钟源 CK_INT• 外部时钟模式 1 :外部输入引脚 TIx ( x=1,2,3,4 )• 外部时钟模式 2 :外部触发输入 ETR• 内部触发输入 (ITRx)
1.3 内部时钟源 (CK_INT)
内部时钟 CK_INT 即来自于芯片内部,等于 72M ,一般情况下,我们都是使用内部时钟。当从模 式控制寄存器 TIMx_SMCR 的 SMS 位等于 000 时,则使用内部时钟。
1.4 控制器
高级控制定时器控制器部分包括触发控制器、从模式控制器以及编码器接口。触发控制器用来针 对片内外设输出触发信号,比如为其它定时器提供时钟和触发 DAC/ADC 转换。编码器接口专门针对编码器计数而设计。从模式控制器可以控制计数器复位、启动、递增 / 递减、 计数。有关控制器部分只需熟练阅读寄存器描述即可。
1.5 时基单元
原理图同基本定时器,但计数方式不同于基本定时器和增加一个重复计数器RCR
高级控制定时器的计数器有三种计数模式,分别为递增计数模式、递减计数模式和递增 /递减 (中 心对齐) 计数模式。(1) 递增计数模式下,计数器从 0 开始计数,每来一个 CK_CNT 脉冲计数器就增加 1 ,直到计数器 的值与自动重载寄存器 ARR 值相等,然后计数器又从 0 开始计数并生成计数器上溢事件,计数 器总是如此循环计数。/*如果禁用重复计数器,在计数器生成上溢事件就马上生成更新事件 (UEV) ; 如果使能重复计数器,每生成一次上溢事件重复计数器内容就减 1 ,直到重复计数器内容为 0 时 才会生成更新事件。*/(2) 递减计数模式下,计数器从自动重载寄存器 ARR 值开始计数,每来一个 CK_CNT 脉冲计数 器就减 1 ,直到计数器值为 0 ,然后计数器又从自动重载寄存器 ARR 值开始递减计数并生成计数器下溢事件,计数器总是如此循环计数。/*如果禁用重复计数器,在计数器生成下溢事件就马上生 成更新事件;如果使能重复计数器,每生成一次下溢事件重复计数器内容就减 1 ,直到重复计数器内容为 0 时才会生成更新事件。*/(3) 中心对齐模式下,计数器从 0 开始递增计数,直到计数值等于 (ARR-1) 值生成计数器上溢事 件,然后从 ARR 值开始递减计数直到 1 生成计数器下溢事件。然后又从 0 开始计数,如此循环。 每次发生计数器上溢和下溢事件都会生成更新事件。
重复计数器 RCR在基本 / 通用定时器发生上 / 下溢事件时直接就生成更新事件,但对于高级控制定时器却不是这样, 高级控制定时器在硬件结构上多出了重复计数器,在定时器发生上溢或下溢事件是递减重复计数器的值,只有当重复计数器为 0 时才会生成更新事件。在发生 N+1 个上溢或下溢事件 (N 为 RCR 的值) 时产生更新事件。
2. 输入捕获
输入捕获可以对输入的信号的上升沿,下降沿或者双边沿进行捕获,常用的有测量输入信号的脉宽和测量 PWM 输入信号的频率和占空比这两种。输入捕获的大概的原理就是,当捕获到信号的跳变沿的时候,把计数器 CNT 的值锁存到捕获寄存器 CCR 中,把前后两次捕获到的 CCR 寄存器中的值相减,就可以算出脉宽或者频率。如果捕获的脉宽的时间长度超过你的捕获定时器的周期,就会发生溢出,这个我们需要做额外的处理。(注意这个)
2.1 原理框图
2.1.1 输入通道
需要被测量的信号从定时器的外部引脚 TIMx_CH1/2/3/4 进入,通常叫 TI1/2/3/4 ,在后面的捕获讲解中对于要被测量的信号我们都以 TIx 为标准叫法。
2.1.2 输入滤波器和边沿检测器
当输入的信号存在高频干扰的时候,我们需要对输入信号进行滤波,即进行重新采样,根据采样定律,采样的频率必须大于等于两倍的输入信号。比如输入的信号为 1M ,又存在高频的信号干扰,那么此时就很有必要进行滤波,我们可以设置采样频率为 2M ,这样可以在保证采样到有效信号的基础上把高于 2M 的高频干扰信号过滤掉。滤波器的配置由 CR1 寄存器的位 CKD[1:0] 和 CCMR1/2 的位 ICxF[3:0] 控制x为通道第几个。从 ICxF 位的描述 可知,采样频率 f SAMPLE 可以由 f CK_INT 和 f DTS 分频后的时钟提供,其中是 f CK_INT 内部时钟, f DTS是 f CK_INT 经过分频后得到的频率,分频因子由 CKD[1:0] 决定,可以是不分频, 2 分频或者是 4 分频。边沿检测器用来设置信号在捕获的时候是什么边沿有效,可以是上升沿,下降沿,或者是双边沿,具体的由 CCER 寄存器的位 CCxP 和 CCxNP 决定。
2.1.3 捕获通道
捕获通道就是图中的 IC1/2/3/4 ,每个捕获通道都有相对应的捕获寄存器 CCR1/2/3/4 ,当发生捕获的时候,计数器 CNT 的值就会被锁存到捕获寄存器中。这里我们要搞清楚输入通道和捕获通道的区别,输入通道是用来输入信号的,捕获通道是用来捕获输入信号的通道,一个输入通道的信号可以同时输入给两个捕获通道。比如输入通道TI1 的信号经过滤波边沿检测器之后的 TI1FP1 和 TI1FP2 可以进入到捕获通道 IC1 和 IC2 ,其实这就是我们后面要讲的 PWM 输入捕获,只有一路输入信号( TI1 )却占用了两个捕获通道( IC1 和 IC2 )。当只需要测量输入信号的脉宽时候,用一个捕获通道即可。输入通道和捕获通道的映射关系具体由寄存器 CCMRx 的位 CCxS[1:0] 配置。
2.1.4 预分频器
ICx 的输出信号会经过一个预分频器,用于决定发生多少个事件时进行一次捕获。具体的由寄存 器 CCMRx 的位 ICxPSC 配置,如果希望捕获信号的每一个边沿,则不分频。
2.1.5 捕获寄存器CCR
经过预分频器的信号 ICxPS 是最终被捕获的信号,当发生捕获时(第一次),计数器 CNT 的值会 被锁存到捕获寄存器 CCR 中,还会产生 CCxI 中断,相应的中断位 CCxIF (在 SR 寄存器中)会 被置位,通过软件或者读取 CCR 中的值可以将 CCxIF 清 0 。如果发生第二次捕获(即重复捕获: CCR 寄存器中已捕获到计数器值且 CCxIF 标志已置 1 ),则捕获溢出标志位 CCxOF (在 SR 寄存器中)会被置位,CCxOF 只能通过软件清零。
2.2 输入捕获结构体
typedef struct {
uint16_t TIM_Channel; // 输入通道选择
uint16_t TIM_ICPolarity; // 输入捕获边沿触发选择,可选上升沿触发.下降沿触发或边沿跳变触发
uint16_t TIM_ICSelection; // 输入捕获选择
uint16_t TIM_ICPrescaler; // 输入捕获预分频器
uint16_t TIM_ICFilter; // 输入捕获滤波器
} TIM_ICInitTyp
(3) TIM_ICSelection :输入通道选择,捕获通道 ICx 的信号可来自三个输入通道,分别为TIM_ICSelection_DirectTI 、 TIM_ICSelection_IndirectTI 或 TIM_ICSelection_TRC ,(直接映射或者间接映射)具体的区别见图 输入通道与捕获通道 IC 的映射图 。如果是普通的输入捕获, 4 个通道都可以使用,如果是 PWM 输入则只能使用通道 1 和通道 2 。(4) TIM_ICPrescaler :输入捕获通道预分频器,可设置 1 、 2 、 4 、 8 分频,它设定 CCMRx 寄存器 的 ICxPSC[1:0] 位的值。如果需要捕获输入信号的每个有效边沿,则设置 1 分频即可。(5) TIM_ICFilter :输入捕获滤波器设置,可选设置 0x0 至 0x0F 。 一般我们不使用滤波器,即设置为 0。
2.3 断路和死区结构体 TIM_BDTRInitTypeDef 用于断路和死区参数的设置
typedef struct {
uint16_t TIM_OSSRState; // 运行模式下的关闭状态选择
uint16_t TIM_OSSIState; // 空闲模式下的关闭状态选择
uint16_t TIM_LOCKLevel; // 锁定配置
uint16_t TIM_DeadTime; // 死区时间
uint16_t TIM_Break; // 断路输入使能控制
uint16_t TIM_BreakPolarity; // 断路输入极性
uint16_t TIM_AutomaticOutput; // 自动输出使能
} TIM_BDTRInitTypeDef;
3.输出比较
输出比较就是通过定时器的外部引脚对外输出控制信号,有冻结、将通道 X ( x=1,2,3,4 )设置为 匹配时输出有效电平、将通道 X 设置为匹配时输出无效电平、翻转、强制变为无效电平、强制变 为有效电平、PWM1 和 PWM2 这八种模式,具体使用哪种模式由寄存器 CCMRx 的位 OCxM[2:0] 配置。其中 PWM 模式是输出比较中的特例,使用的也最多。
3.1 原理框图
3.1.1 比较寄存器
当计数器 CNT 的值跟比较寄存器 CCR 的值相等的时候,输出参考信号 OCxREF 的信号的极性 就会改变,其中 OCxREF=1 (高电平)称之为有效电平, OCxREF=0 (低电平)称之为无效电平, 并且会产生比较中断 CCxI ,相应的标志位 CCxIF ( SR 寄存器中)会置位。然后 OCxREF 再经过 一系列的控制之后就成为真正的输出信号 OCx/OCxN 。
3.1.2 死区发生器
在生成的参考波形 OCxREF 的基础上,可以插入死区时间,用于生成两路互补的输出信号 OCx 和 OCxN ,死区时间的大小具体由 BDTR 寄存器的位 DTG[7:0] 配置。死区时间的大小必须根据与 输出信号相连接的器件及其特性来调整。下面我们简单举例说明下带死区的 PWM 信号的应用,我们以一个板桥驱动电路为例。
在这个半桥驱动电路中, Q1 导通,Q2 截止,此时我想让 Q1 截止 Q2 导通,肯定是要先让 Q1 截 止一段时间之后,再等一段时间才让 Q2 导通,那么这段等待的时间就称为死区时间,因为 Q1 关闭需要时间(由 MOS 管的工艺决定)。如果 Q1 关闭之后,马上打开 Q2 ,那么此时一段时间 内相当于 Q1 和 Q2 都导通了,这样电路会短路。图带死区插入的互补输出 是针对上面的半桥驱动电路而画的带死区插入的 PWM 信号,图中的死区时间要根据 MOS 管的工艺来调节。
在输出比较的输出控制中,参考信号 OCxREF 在经过死区发生器之后会产生两路带死区的互补 信号 OCx_DT 和 OCxN_DT (通道 1~3 才有互补信号,通道 4 没有,其余跟通道 1~3 一样),这 两路带死区的互补信号然后就进入输出控制电路,如果没有加入死区控制,那么进入输出控制电 路的信号就直接是 OCxREF 。
3.2 输出比较结构体
typedef struct {
uint16_t TIM_OCMode; // 比较输出模式
uint16_t TIM_OutputState; // 比较输出使能
uint16_t TIM_OutputNState; // 比较互补输出使能
uint32_t TIM_Pulse; // 脉冲宽度
uint16_t TIM_OCPolarity; // 输出极性,输出控制高电平有效还是低电平有效
uint16_t TIM_OCNPolarity; // 互补输出极性,互补输出控制高电平有效还是低电平有效
uint16_t TIM_OCIdleState; // 空闲状态下比较输出状态,1为空闲高电平,0为空闲低电平
uint16_t TIM_OCNIdleState; // 空闲状态下比较互补输出状态,1为空闲高电平,0为空闲低电平
} TIM_OCInitTypeDef;
3.4 编程步骤
(1)
定时器用到的
GPIO
初始化
(2)
定时器时基结构体
TIM_TimeBaseInitTypeDef
初始化
(3)
定时器输出比较结构体
TIM_OCInitTypeDef
初始化
(4)
定时器刹车和死区结构体
TIM_BDTRInitTypeDef
初始化