1.高级定时器的高级功能
STM32ZET6F103系列芯片中配置了两个高级定时器:TIM1和TIM8。C8T6F103系列中配置了一个高级定时器:TIM1。其余系列芯片在使用前需要详细查阅芯片数据手册。高级定时器除了拥有通用定时器的所有功能外,还增加了三个高级功能:
(1)死区时间可编程的互补输出
(2)断路输入信号(刹车输入信号)
(3)重复计数器
2.高级定时器功能框图
下图是高级定时器的功能框图,通过对比通用定时器的功能框图可以发现,高级定时器的功能框图中增加了重复次数计数器、REP寄存器、DTG寄存器、DTG控制电路、输出控制电路、BRK输入电路、互补输出引脚等,通过这些新增的硬件电路和寄存器,实现了死区时间可编程、刹车输入信号、重复计数等高级功能。

3.高级功能介绍
(1)死区时间可编程的互补输出
高级定时器的通道1/2/3可以分别输出2路互补信号:CHx和CHxN。(注意:通道4没有此功能)互补信号:频率周期相等,相位差180°。

死区时间可编程的互补输出一般用于驱动H桥电路中,**H桥电路:**用于驱动电流较大的负载,例如电机。

在上图中:
CH1输出高电平时,Q1和Q4导通,电机正传
CHN1输出高电平时,Q2和Q3导通,电机反转
理论上,CH1和CH1N永远相反,所以可以非常方便的控制电机的转动。但是由于MOS管的特性:开启动作快,关断动作慢,如果不对这个时间差进行调整,在真实的运行环境中,会有一段时间内Q1、Q2、Q3、Q4同时导通,这种情况会直接导致短路,烧毁芯片。
为了避免以上情况,就需要用到高级定时器中的死区时间来做调整。
下图是带死区插入的互补输出:

OCxREF:标准信号
OCx和OCxN的低电平立即变化
OCx和OCxN的高电平延迟变化
上面的解决思路是:
在驱动电平进行翻转时,互补输出的两个引脚在即将输出有效电平(上图中的有效电平是高电平)时,插入一段可以编程的延时,这段时间正好是MOS管的开关的速度差。这样就避免了短路的问题。
简言之:有效电平到无效电平:立即翻转;无效电平到有效电平:延时后翻转。
(2)断路输入信号(刹车输入信号)

断路输入信号(刹车输入信号)的作用是通过检测一个触发事件,当对应的事件发生时,关断定时器对应通道的输出。外部输出或时钟失效事件可以触发刹车动作。
(3)重复计数器
次重复计数器主要用于实现重复多次的计数器溢出,可以将定时器的计时时间延长。重复次数计数器 中的值是通过RCR寄存器设置,RCR寄存器中的REP控制位共计8位,因此,可以实现0-255次的重复溢出。
自动重装载寄存器 计数完毕后会向重复次数计数器 发送一个事件,使得其中的数值减一 ,当重复次数计数器中的值等于0时候,发出中断事件。
例:如果REP的是为2时,CNT计数溢出3次产生一次更新事件。
可以用这个功能产生固定周期数的PWM输出
4.高级定时器寄存器介绍
在之前的基本定时器和通用定时器中的介绍可知,在定时器中存在着一些影子寄存器,这是为了方便在定时器运行中改变一些关键的参数。下图是高级定时器中存在影子的寄存器。

5.实验--输出有限个周期的PWM波
(1)需求
用寄存器实现。输出5个周期的PWM波,频率2Hz,观察发光二极管闪烁5次,或者
用示波器观察波形。
需求实现思路:使用高级定时器的重复计数器,当计数器溢出时,在溢出中断中停止定时器工作。重复计数器寄存器的值设置为4,即可输出5个周期的PWM波,发光二极管会闪烁5次。
(2)硬件电路

(3)整体配置思路
使用寄存器实现,主要的配置思路如下:
1.打开定时器、GPIO对应模块的时钟
2.配置对应GPIO引脚配置为复用功能推挽输出模式,CNF-10;MODE-11
3.定时的器基础参数配置:
*
- 预加载
- 配置预分频系数
- 配置自动重装载计数器
- 计数方向:向上计数
- 循环次数设置
4.PWM配置 -
- 通道模式配置
- 设置PWM的初始占空比
- 通道极性选择
- 通道使能
- 开主输出使能(注意:这个配置是高级定时器中需要额外增加的)
5.将设置的值都刷新到对应的寄存器中, -
- 设置URS位,在更新UG时不产生中断,仅在定时器上下溢出时或发生更新事件时触发中断
- 手动产生一个更新事件,将设置的值都刷新到对应的影子寄存器中
6.配置中断 -
- 使能定时器的更新事件中断,当重复计数器中的值为0后再次向下减时产生更新事件
- 中断组、优先级配置
7.将开启定时器、关闭定时器包装成独立的函数,以便调用
8.配置中断服务函数,在中断中关闭定时器 -
- 清除中断标志位
- 关闭定时器
(4)实现代码
cpp
#include "tim.h"
void Tim1_Init(void)
{
// 1.打开时钟
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
// 2.通道1输出PWM,引脚GPIOA8引脚配置为复用功能推挽输出模式,CNF-10;MODE-11
GPIOA->CRH |= GPIO_CRH_CNF8_1;
GPIOA->CRH &= ~GPIO_CRH_CNF8_0;
GPIOA->CRH |= GPIO_CRH_MODE8;
// 3.定时器基础配置
// 3.1.预加载功能配置,开启预加载
TIM1->CR1 |= TIM_CR1_ARPE;
// 3.2.配置预分频系数,7199,分频后得到10KHz
TIM1->PSC = 7199;
// 3.3.配置自动重装载计数器,4999,得到500ms一次溢出
TIM1->ARR = 4999;
// 3.4.计数方向:向上计数
TIM1->CR1 &= ~TIM_CR1_DIR;
// 3.5.循环次数设置
TIM1->RCR = 4;
// 4.PWM配置
// 4.1通道1模式配置,输出模式:CC1S-00,PWM模式1:OC1M-110
TIM1->CCMR1 &= ~TIM_CCMR1_CC1S;
TIM1->CCMR1 |= TIM_CCMR1_OC1M_2;
TIM1->CCMR1 |= TIM_CCMR1_OC1M_1;
TIM1->CCMR1 &= ~TIM_CCMR1_OC1M_0;
// 4.2.设置CCR1的值,设定PWM的初始占空比
TIM1->CCR1 = 2500;
// 4.3.通道极性选择,低电平有效
TIM1->CCER |= TIM_CCER_CC1P;
// 4.4.通道使能
TIM1->CCER |= TIM_CCER_CC1E;
// 4.5.开主输出使能
TIM1->BDTR |= TIM_BDTR_MOE;
// 5.手动产生一个更新事件,将设置的值都刷新到对应的影子寄存器中
// 5.1.设置URS位,在更新UG时不产生中断,仅在定时器上下溢出时或发生更新事件时触发中断
TIM1->CR1 |= TIM_CR1_URS;
TIM1->EGR |= TIM_EGR_UG;
// 6.配置中断
// 6.1.使能定时器的更新事件中断,当重复计数器中的值为0后再次向下减时产生更新事件
TIM1->DIER |= TIM_DIER_UIE;
// 6.2.中断组、优先级配置
NVIC_SetPriorityGrouping(3);
NVIC_SetPriority(TIM1_UP_IRQn, 3);
NVIC_EnableIRQ(TIM1_UP_IRQn);
}
// 开启定时器
void TIM1_Start(void)
{
TIM1->CR1 |= TIM_CR1_CEN;
}
// 关闭定时器
void TIM1_Stop(void)
{
TIM1->CR1 &= ~TIM_CR1_CEN;
}
// 中断服务函数
void TIM1_UP_IRQHandler(void)
{
// 判断中断源
if(TIM1->SR & TIM_SR_UIF)
{
// 1.清除中断标志位
TIM1->SR &= ~TIM_SR_UIF;
// 关闭定时器
TIM1_Stop();
}
}