STM32F7学习笔记15:定时器详解
1. SysTick系统定时器
1.1 SysTick
SysTick—系统定时器是属于CM7内核中的一个外设,内嵌在NVIC中。
系统定时器是一个24bit的向下递减的计数器,计数器每计数一次的时间为1/SYSCLK,一般我们设置系统时钟SYSCLK等于216M。当重装载数值寄存器的值递减到0的时候,系统定时器就产生一次中断,以此循环往复。
因为SysTick是属于CM7内核的外设,所以所有基于CM7内核的单片机都具有这个系统定时器,使得软件在CM7单片机中可以很容易的移植。
系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。
1.2 SysTick寄存器
SysTick—系统定时有4个寄存器,如下表所示:
寄存器名称 | 寄存器描述 |
---|---|
CTRL | SysTick控制及状态寄存器 |
LOAD | SysTick重装载数值寄存器 |
VAL | SysTick当前数值寄存器 |
CALIB | SysTick校准数值寄存器 |
SysTick控制及状态寄存器
位段 | 名称 | 类型 | 复位值 | 描述 |
---|---|---|---|---|
16 | COUNTFLAG | R/W | 0 | 如果在上次读取本寄存器 后, SysTick 已经计到 了 0,则该位为 1。 |
2 | CLKSOURCE | R/W | 0 | 时钟源选择位,0=外部 时钟,1=处理器时钟A HB |
1 | TICKINT | R/W | 0 | 1=SysTick倒数 计数到 0时产生 SysTick异常请求,0=数到 0 时无动作。也可以通过读 取COUNTFLAG标 志位来确定计数器是否递 减到0 |
0 | ENABLE | R/W | 0 | SysTick 定时器的使能位 |
重装载数值寄存器
位段 | 名称 | 类型 | 复位值 | 描述 |
---|---|---|---|---|
23:0 | RELOAD | R/W | 0 | 当倒数计数至零时,将被重装载的值 |
当前数值寄存器
位段 | 名称 | 类型 | 复位值 | 描述 |
---|---|---|---|---|
23:0 | CURRENT | R/W | 0 | 读取时返回当前倒计数的 值,写它则使之清零,同 时还会清除在SysTi ck控制及状态寄存器中 的COUNTFLAG 标志 |
SysTick校准数值寄存器
位段 | 名称 | 类型 | 复位值 | 描述 |
---|---|---|---|---|
31 | NOREF | R | 0 | 指示是否有参考时钟提供 给处理器0:提供参考时钟1:不提供参考时钟如果器件不提供参考时钟 ,SYST_CSR.C LKSOURCE标志位 为1,不可改写。 |
30 | SKEW | R | 1 | S指示TENMS的值是 否精确0:TENMS是精确值1:TENMS不是精确 值或者不提供不精确的TENMS值可 以影响作为软件实时时钟 节拍器的适用性。 |
23:0 | TENMS | R | 0 | 重新加载 10ms (100Hz) 计时的值, 受系统时钟偏差的错误。 如果值读取为零,校准值未知。 |
1.3 HAL配置SysTick
1. 配置Timebase Source
配置过程如下图所示:
2. SYSTICK定时器溢出中断
在NVIC中可以看到Systick的溢出中断是否开启,如下图所示:
可以看到默认已经打开并且不能取消,优先级是15【数字越大,优先级越高】
在stm32f7xx_it.c中增加HAL_InitTick函数。
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
{
return HAL_ERROR;
}
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
/* Return function status */
return HAL_OK;
}
这个1000U就是溢出中断的时间,计算方法为
如果要更改中断事件,可以改变1000U这个数值,比如改为200,即5ms中断一次。
在stm32f7xx_it.c中还有一个systick_handle函数,在该函数中写入中断执行函数,如下:
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin);
/* USER CODE END SysTick_IRQn 1 */
}
1.4 测试
略
2. TIM 基本定时器
2.1 TIM 简介
定时器(Timer)最基本的功能就是定时,比如定时发送USART数据、定时采集AD数据等。
STM32F767控制器有2个高级控制定时器、10个通用定时器和2个基本定时器,还有2个看门狗定时器。
各个定时器特性如下所示:
其中最大定时器时钟可通过RCC_DCKCFGR寄存器配置为108MHz或者216MHz。
基本定时器主要两个功能:
- 基本定时功能,生成时基,
- 专门用于驱动数模转换器(DAC)。
基本定时器TIM6和TIM7是一个16位向上递增的定时器,当自动重载寄存器(TIMx_ARR)添加一个计数值后并使能TIMx,计数寄存器(TIMx_CNT)就会从0开始递增,当TIMx_CNT的数值与TIMx_ARR值相同时就会生成事件并把TIMx_CNT寄存器清0,完成一次循环过程。
DMA全程Direct Memory Access,即直接存储器访问。简单来讲,它的功能是把数据从一个地址搬运到另一个地址。通常有三个传输方向,分别是内存到内存,内存到外设和外设到内存。
2.2 基本定时器功能框图
基本定时器功能框图如下:
1. 时钟源
基本定时器时钟只能来自内部时钟,高级控制定时器和通用定时器还可以选择外部时钟源或者直接来自其他定时器等待模式。
基本定时器只能使用内部时钟,当TIM6和TIM7控制寄存器1(TIMx_CR1)的CEN位置1时,启动基本定时器,并且预分频器的时钟来源就是CK_INT。
2. 控制器
定时器控制器控制实现定时器功能,控制定时器复位、使能、计数是其基础功能,基本定时器还专门用于DAC转换触发。
3. 计数器
基本定时器计数过程主要涉及到三个寄存器内容,分别是计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)、自动重载寄存器(TIMx_ARR),这三个寄存器都是16位有效数字,即可设置值为0至65535。
预分频器PSC,它有一个输入时钟CK_PSC和一个输出时钟CK_CNT。 输入时钟CK_PSC来源于控制器部分,基本定时器只有内部时钟源所以CK_PSC实际等于CK_INT,即108MHz。 在不同应用场所,经常需要不同的定时频率,通过设置预分频器PSC的值可以非常方便得到不同的CK_CNT,实际计算为:fCK_CNT等于fCK_PSC/(PSC[15:0]+1)。
自动重载寄存器TIMx_ARR用来存放于计数器值比较的数值,如果两个数值相等就生成事件,将相关事件标志位置位,生成DMA和中断输出。
4. 定时器周期计算
定时事件生成时间主要由TIMx_PSC和TIMx_ARR两个寄存器值决定,这个也就是定时器的周期。
比如需要一个1s周期的定时器,具体这两个寄存器值该如何设置内。假设,我们先设置TIMx_ARR寄存器值为9999,即当TIMx_CNT从0开始计算,刚好等于9999时生成事件,总共计数10000次,那么如果此时时钟源周期为100us即可得到刚好1s的定时周期。
2.3 HAL 配置基本定时器
1. 打开基本定时器TIM6
TIM6和TIM7使用的时钟是APB1,从STM32CubeMX的时钟配置中可以看到APB频率是90MHz,如下图所示
如果要定时3s,则FCK_PSC=90M,若设置(PSC+1)=60000,则TIM6计数器的频率实际是15000
即PSC=60000-1=5999
定时3s,则ARR设置为45000即可
在STM32CubeMX中设置相关数据
APB1频率为90MHz,理论上在的可以定时的最大周期为65535/(90000000/65535)
\frac{65535}{\frac{900000000}{65535}}=4.772
点击生成代码。
一般来说,MX生成各种Init代码,但不生成各种callback函数【也许是我不知道怎么生成】,我们需要自己实现相关函数。
MX也不生成定时器开始函数
2. 代码修改
在main.c中添加定时器启动代码:
HAL_TIM_Base_Start_IT(&htim6);
在stm32f7xx.it.c中添加callback函数:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_TIM_IC_CaptureCallback could be implemented in the user file
*/
}
3. 测试
略
3. TIM高级定时器
3.1 高级定时器简介
高级控制定时器(TIM1和TIM8)和通用定时器在基本定时器的基础上引入了外部引脚,可以输入捕获和输出比较功能。
高级控制定时器比通用定时器增加了可编程死区互补输出、重复计数器、带刹车(断路)功能,这些功能都是针对工业电机控制方面。
高级控制定时器时基单元包含一个16位自动重载计数器ARR,一个16位的计数器CNT,可向上/下计数,一个16位可编程预分频器PSC,预分频器时钟源有多种可选,有内部的时钟、外部时钟。还有一个8位的重复计数器RCR,这样最高可实现40位的可编程定时。
STM32F767IGT6的高级/通用定时器的IO分配具体见下表
3.2 高级定时器功能框图
功能框图如下图所示
3.2.1. 时钟源
- 内部时钟源CK_INT
- 外部时钟模式1:外部输入引脚TIx(x=1,2,3,4)
- 外部时钟模式2:外部触发输入ETR
- 内部触发输入(ITRx)
3.2.1.1 内部时钟
内部时钟CK_INT即来自于芯片内部,等于216M,一般情况下,我们都是使用内部时钟。当从模式控制寄存器TIMx_SMCR的SMS位等于000时,则使用内部时钟。
3.2.1.2 外部时钟模式1
功能框图如下:
- 时钟信号输入引脚:当使用外部时钟模式1的时候,时钟信号来自于定时器的输入通道,总共有4个,分别为TI1/2/3/4,即TIMx_CH1/2/3/4。
- 滤波器:如果来自外部的时钟信号的频率过高或者混杂有高频干扰信号的话,我们就需要使用滤波器对信号重新采样,来达到降频或者去除高频干扰的目的,具体的由TIMx_CCMRx的位ICxF[3:0]配置。
- 边沿检测:边沿检测的信号来自于滤波器的输出,在成为触发信号之前,需要进行边沿检测,决定是上升沿有效还是下降沿有效
- 触发选择:当使用外部时钟模式1时,触发源有两个,一个是滤波后的定时器输入1(TI1FP1)和滤波后的定时器输入2(TI2FP2),具体的由TIMxSMCR的位TS[2:0]配置。
- 从模式选择:选定了触发源信号后,最后我们需把信号连接到TRGI引脚,让触发信号成为外部时钟模式1的输入,最终等于CK_PSC,然后驱动计数器CNT计数。具体的配置TIMx_SMCR的位SMS[2:0]为000即可选择外部时钟模式1。
- 使能计数器:经过上面的5个步骤之后,最后我们只需使能计数器开始计数,外部时钟模式1的配置就算完成。使能计数器由TIMx_CR1的位CEN配置。
3.2.1.3 外部时钟模式2
功能框图如下所示
- 时钟信号输入引脚:当使用外部时钟模式2的时候,时钟信号来自于定时器的特定输入通道TIMx_ETR,只有1个。
- 外部触发极性:来自ETR引脚输入的信号可以选择为上升沿或者下降沿有效,具体的由TIMx_SMCR的位ETP配置。
- 外部触发预分频器:由于ETRP的信号的频率不能超过TIMx_CLK(72M)的1/4,当触发信号的频率很高的情况下,就必须使用分频器来降频,具体的由 TIMx_SMCR的位ETPS[1:0]配置。
- 滤波器:如果ETRP的信号的频率过高或者混杂有高频干扰信号的话,我们就需要使用滤波器对ETRP信号重新采样,来达到降频或者 去除高频干扰的目的。
- 从模式选择:经过滤波器滤波的信号连接到ETRF引脚后,触发信号成为外部时钟模式2的输入,最终等于CK_PSC,然后驱动计数器CNT计数。
- 使能计数器:经过上面的5个步骤之后,最后我们只需使能计数器开始计数,外部时钟模式2的配置就算完成。使能计数器由TIMx_CR1的位CEN配置。
3.2.1.4 内部触发输入
内部触发输入是使用一个定时器作为另一个定时器的预分频器。
其他略
3.2.2 控制器
高级定时器控制器部分包括触发控制器、从模式控制器以及编码器接口。触发控制器用来针对片内外设输出触发信号,比如为其它定时器提供时钟和触发DAC/ADC转换。
3.2.3 时基单元
时机单元功能框图下图
高级控制定时器时基单元功能包括四个寄存器,分别是计数器寄存器(CNT)、预分频器寄存器(PSC)、自动重载寄存器(ARR)和重复计数器寄存器(RCR)。
3.2.4 输入捕获
输入捕获功能框图如下:
输入捕获可以对输入的信号的上升沿、下降沿或者双边沿进行捕获,常用的有测量输入信号的脉宽和测量PWM输入信号的频率和占空比这两种。
3.2.5 输出比较
输出比较功能框图如下:
3.2.6 断路功能
断路功能就是电机控制的刹车功能,使能断路功能时,根据相关控制位状态修改输出信号电平。在任何情况下,OCx和OCxN输出都不能同时为有效电平,这关系到电机控制常用的H桥电路结构原因。
3.3 输入捕获应用
输入捕获一般应用在两个方面,一个方面是脉冲跳变沿时间测量,另一方面是PWM输入测量。
3.3.1 测量脉宽或者频率
测量原理如下:
3.3.2 PWM输入模式
测量脉宽和频率还有一个更简便的方法就是使用PWM输入模式。与上面那种只使用一个捕获寄存器测量脉宽和频率的方法相比,PWM输入模式需要占用两个捕获寄存器。
测量原理如下:
3.4 输出比较应用
PWM输出模式
PWM输出就是对外输出脉宽(即占空比)可调的方波信号,信号频率由自动重装寄存器ARR的值决定,占空比由比较寄存器CCR的值决定。
3.5 HAL 操作高级定时器
略,后续制作数据采集卡时详细使用
4. LPTIM 低功耗定时器
略,后续详细使用