Main Takeaway
Following 哈工深上传到B站的电控组培训来入门robomaster电控组,我购买了普中科技玄武套餐开发板作为硬件。
本篇介绍我学习TIM的见闻
TIM
简介
定时器Timer分类:STM32中的TIM分为三大类:基本定时器(TIM6和TIM7)、通用定时器(TIMx)和高级控制定时器(TIM1和TIM8)
基本定时器具有最基本的定时功能,可编程控制定时周期,计数器溢出(即设置定时间隔,然后自动重装载为0,重新计数)能产生中断/DMA请求。
通用定时器除了基本定时器的功能外,还可配置计数器装载方式,具有4个独立通道,每个通道均可进行输入捕获、输出比较、PWM输出以及单脉冲模式。中断源更多(向上溢出/向下溢出、计数器初始化/启动/停止、输入捕获、输出比较等) HAL_Delay(ms);
高级定时器在通用定时器的基础上,还增加了数个功能:可输出嵌入死区时间的互补PWM、允许在指定数目的计数器周期之后更新定时器寄存器的重复计数器、刹车输入信号可以将定时器输出信号置于复位或者一个已知状态,中断源也多了一个刹车信号输入。
Notes:可编程定时器的主要部分是一个带有自动重装载的16位累加计数器,计数器的时钟通过一个预分频器得到。软件可以读写计数器、自动重装载寄存器和预分频寄存器,即使计数器运行时也可以操作。
死区:为了避免功率元件烧毁而产生的的一段延迟时间。
通常,大功率电机、变频器等,末端都是由大功率管、IGBT等元件组成的H桥或3相桥。每个桥的上半桥和下半桥是是绝对不能同时导通的,但高速的PWM驱动信号在达到功率元件的控制极时,往往会由于各种各样的原因产生延迟的效果,造成某个半桥元件在应该关断时没有关断,造成功率元件烧毁。死区就是在上半桥关断后,延迟一段时间再打开下半桥或在下半桥关断后,延迟一段时间再打开上半桥,从而避免功率元件烧毁。这段延迟时间就是死区。(就是上、下半桥的元件都是关断的)死区时间控制在通常的低端单片机所配备的PWM中是没有的。
TIM的刹车功能是一种用于控制PWM输出的技术,它可以在检测到外部信号或者内部事件时,立即停止PWM输出,并将输出管脚置为预设的状态,以避免负载端出现异常或者危险的情况。
基本定时器介绍
TIM6和TIM7为基本定时器,两者资源相互独立不共享。两者各有一个可编程定时器。
时基单元
时基单元是一种用于产生定时或计数功能的模块。
时基单元包含:
计数器寄存器(TIMx_CNT):它可以对分频后的时钟信号进行计数,从而实现定时或计数功能。计数器的计数方向由TIMx_CR1寄存器的DIR位设置,它可以是向上计数或向下计数。计数器的当前值由TIMx_CNT寄存器保存,它是一个16位的只读寄存器。
预分频寄存器(TIMx_PSC):它可以对输入的时钟信号进行分频,从而降低计数器的计数速度,增加计数范围。分频器的分频比由TIMx_PSC寄存器设置,它是一个16位的预装载寄存器,即它有一个影子寄存器和一个预装载寄存器,当发生更新事件时,预装载寄存器的值会被复制到影子寄存器中。
自动重装载寄存器(TIMx_ARR):它可以为计数器设置一个最大值或最小值,当计数器达到这个值时,会发生溢出或下溢,并触发更新事件,该事件可用于产生中断。自动重装载寄存器由TIMx_ARR寄存器设置,它也是一个16位的预装载寄存器,具有影子寄存器和预装载寄存器。
Tips:自动重装载寄存器是预加载的,每次读写自动重装载寄存器时,实际上是通过读写预加载寄存器实现。根据TIMx_CR1寄存器中的自动重装载预加载使能位(ARPE),写入预加载寄存器的内容能够立即或在每次更新事件时,传送到它的影子寄存器。
预分频
预分频可以以系数介于1至65536之间的任意数值对计数器时钟分频。它是通过一个16位寄存器(TIMx_PSC)的计数实现分频。因为TIMx_PSC控制寄存器具有缓冲,可以在运行过程中改变它的数值,新的预分频数值将在下一个更新事件时起作用。(随时可以写)
计数器模式
计数器从0累加计数到自动重装载数值(TIMx_ARR寄存器:AutoReload Register),然后重新从0开始计数并产生一个计数器溢出事件。每次计数器溢出时可以产生更新事件。ARR=36:

Tips:ARR没有预装载则为FF,只有向上计数
通用定时器介绍
在STM32F10x系列中,通用定时器有TIM2、TIM3、TIM4和TIM5,每个定时器都是完全独立的,没有互相共享任何资源。它们可以一起同步操作。
计数器模式
- 向上计数:当TIMx_CR1寄存器中的DIR位为低的时候执行向上计数。
- 向下计数:当TIMx_CR1寄存器中的DIR位为高时时候执行向下计数。
- 中央对齐模式(向上/向下计数)

输入捕获模式
在输入捕获模式下,当检测到信号上相应的边沿后,计数器的当前值被锁存到捕获/比较寄存器(TIMx_CCRx)中,同时产生输入捕获事件,该事件可以被用于产生中断。
PWM模式
脉冲宽度调制模式可以产生一个由TIMx_ARR寄存器确定频率(周期)、由TIMx_CCRx寄存器确定占空比的信号。
Tips:eg TIMx_CCRx为8,则计数器小于8为低电平,大于等于8为高电平
OCxREF极性与电平相反,CCxIF是中断
在PWM模式(模式1或模式2)下, TIMx_CNT和TIMx_CCRx始终在进行比较, (依据计数器的计数方向)以确定是否符合TIMx_CCRx≤TIMx_CNT或者TIMx_CNT≤TIMx_CCRx。
TIM中断
定时器溢出中断
定时器输入捕获中断
TIM重要寄存器
计数器(TIMx_CNT)
预分频器(TIMx_PSC)
自动重装载寄存器(TIMx_ARR)
捕获/比较寄存器(TIMx_CCRx)
TIM API
1 | HAL_StatusTypeDef HAL_TIM_IC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel) |
1 | /** |
1 | /** |
实验
实现简单定时实验
CubeMX
预分频PSC : 72-1(从0开始计数所以要减1)
counter period: 20000-11
2
3
4
5
6
7
8
9
10
11
12
13HAL_TIM_Base_Start_IT(&htim6);//TIM6,7是基本定时器
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static int cnt = 0;
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_All, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOF, showNum(cnt), GPIO_PIN_RESET);
cnt++;
if (cnt == 9)
{
cnt = 0;
}
}
实现PWM输出实验
输出指定周期和占空比的PWM波,驱动蜂鸣器。
CubeMX
通用定时器:要看原理图选择是哪个channel
clock source:internal clock
默认的串口要修改成我们想要设置为TIM的那个串口
Tips:无TIM可以短接
My fault:PSC预分频设置为0无声音。。。
1 | TIM4->ARR = M_Do; |
实现输入捕获实验
读取上一个实验中输出的PWM一个周期内的高电平时间和低电平时间。1
2int tim4_last_count, tim4_count, low_time, high_time;
// 定时器输入捕获中断回调函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
static uint8_t flag = 0; //0代表上升沿触发;1代表下降沿触发
tim4_last_count = tim4_count;
if(flag == 0)
{
tim4_count = TIM4->CCR4;
// 计算低电平时间
low_time = tim4_count - tim4_last_count;
if(low_time < 0) low_time += 19999;
else low_time += 1;
// 修改输入捕获触发方式为下降沿触发
TIM_RESET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_4);
TIM_SET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_4, TIM_ICPOLARITY_FALLING);
flag = 1;
}
else if(flag == 1)
{
tim4_count = TIM4->CCR4;
// 计算高电平时间
high_time = tim4_count - tim4_last_count+1;
// 修改输入捕获触发方式为上升沿触发
TIM_RESET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_4);
TIM_SET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_4, TIM_ICPOLARITY_RISING);
flag = 0;
}
}
Tips:project中没有输入捕获的回调函数,必须自己写
计数器从0开始计数(有时需要+1)