> 技术文档 > STM32 HAL库开发学习13. 定时器及基本定时器使用_stm32定时器hal库

STM32 HAL库开发学习13. 定时器及基本定时器使用_stm32定时器hal库


STM32 HAL库开发学习13. 定时器及基本定时器使用

  • 一、定时器概述
    • 1. 定时器简介
    • 2. 定时器常见类型
    • 3. STM32定时器特性表
      • F1系列
      • H7系列
  • 二、基本定时器
    • 1. 基本定时器功能简介
    • 2. 时钟树
    • 3. STM32 定时器计数模式
    • 4. STM32 定时器相关寄存器
      • (1)TIMx_CR1 设置ARR寄存器是否有缓冲、关闭/开启计数器
        • 位7:ARPE: 自动重载预装载使能(Auto-reload preload enable)
        • 位0:CEN:计数器使能(Counter enable)
      • (2)TIMx_DIER
        • 位8: UDE:更新DMA请求使能(Update DMA request enable)
        • 位0:UIE:更新中断使能(Update interrupt enable)
      • (3)TIMx_SR 状态寄存器
        • 位0: UIF:更新中断标志(Update interrupt flag)
      • (4)TIMx_CNT 计数器寄存器
      • (5)TIMx_PSC 预分频器寄存器
      • (6)TIMx_ARR 自动重装载寄存器
    • 5. 定时器溢出时间计算方法
  • 三、定时器配置步骤
    • 1. 配置定时器基础工作参数
    • 2. 定时器基础MSP初始化
    • 3. 使能更新中断并启动计数器
    • 4. 设置优先级,使能中断
    • 5. 编写中断服务函数
    • 6. 清除中断标志位
  • 四、定时器配置实例
    • 1. STM32CubeMX配置 启用TIM6
    • 2. 启动 TIM6全局中断
    • 3. 生成的部分代码
      • main.c里TIM6初始化
      • stm32f1xx_it.c 中断
    • 4. 手工添加代码
      • (1)TIM6初始化的代码里,添加启动中断
      • (2)实现中断回调函数

一、定时器概述

1. 定时器简介

实现定时器的方式一般有软件、硬件两种方式,本文主要针对STM32的硬件定时器。

定时器的核心是一个计数器,该计数器会按照一定的时钟频率进行加 1 或减 1 操作。当计数器的值达到预设的阈值(即自动重装载值)时,会触发特定的事件,如产生中断、更新输出信号等。同时,计数器可以根据配置自动重新开始计数,形成周期性的定时操作。

2. 定时器常见类型

STM32 HAL库开发学习13. 定时器及基本定时器使用_stm32定时器hal库

3. STM32定时器特性表

F1系列

定时器类型 定时器编号 位宽 计数模式 主要功能 总线 高级控制定时器 TIM1、TIM8 16 位 向上、向下、向上/向下(中央对齐) PWM 输出(带死区插入)、4个输入捕获、互补输出、刹车输入、编码器接口、触发 DAC/ADC APB2 通用定时器 TIM2、TIM3、TIM4、TIM5 16 位(TIM2、TIM5 为 32 位) 向上、向下、向上/向下(中央对齐) PWM 输出、4个输入捕获、输出比较、编码器接口、触发 DAC/ADC APB1 基本定时器 TIM6、TIM7 16 位 向上 定时、触发 DAC/ADC APB1

H7系列

定时器类型 定时器 计数器位数 计数模式 预分频系数 产生 DMA 请示 捕获/比较通道 互补输出 高级定时器 TIM1、TIM8 16 位 向上 1 - 65536 支持 4 个 有 通用定时器 TIM2、TIM5 32 位 向上、向下、中央对齐 1 - 65536 支持 4 个 无 通用定时器 TIM3、TIM4 16 位 向上、向下、中央对齐 1 - 65536 支持 4 个 无 通用定时器 TIM12 16 位 向上 1 - 65536 不支持 2 个 无 通用定时器 TIM13、TIM14 16 位 向上 1 - 65536 不支持 1 个 无 通用定时器 TIM15 16 位 向上 1 - 65536 支持 2 个 有 基本定时器 TIM16、TIM17 16 位 向上 1 - 65536 支持 1 个 有 基本定时器 TIM6、TIM7 16 位 向上 1 - 65536 支持 1 个 有

二、基本定时器

1. 基本定时器功能简介

基本定时器有TIM6/TIM7,其主要特性有:

  • 基本定时器使用 16 位的计数器,计数模式为向上计数,即从 0 开始计数,逐步递增,直到达到自动重载寄存器(ARR)中设置的值,然后计数器会重新归零并开始下一轮计数。
  • 可编程预分频器可以对定时器的时钟源进行分频,预分频系数范围通常为 1 - 65536。通过设置预分频寄存器(PSC)的值,可以调整定时器的计数频率,从而实现不同的定时精度。
  • 自动重载寄存器(ARR)用于存储计数器的上限值。当计数器的值达到 ARR 中设置的值时,会产生更新事件,计数器会重新归零。
  • 计数器溢出(达到 ARR 值)时会产生更新事件。更新事件可以用于触发一些操作,例如触发 DAC(数模转换器)或 ADC(模数转换器)的转换。
  • 基本定时器可以产生 DMA(直接内存访问)请求。当定时器产生更新事件时,可以触发 DMA 传输,将数据从一个内存位置传输到另一个内存位置,而无需 CPU 的干预,提高系统效率。

2. 时钟树

STM32 HAL库开发学习13. 定时器及基本定时器使用_stm32定时器hal库
在STM32F1中,TIM1和TIM8是挂载在APB2总线上,(最大稳定频率72MHz)
而TIM2~5挂载在APB1总线上(最大频率36MHz)。

并不是挂载在APB1上,定时器频率最大就是36MHz,还要取决于预分频系数,如下图所示的 TIM1 Timer x1,2 Multiplier。
STM32 HAL库开发学习13. 定时器及基本定时器使用_stm32定时器hal库

3. STM32 定时器计数模式

计数器模式 溢出条件 向上 CNT==ARR 向下 CNT==0 中心对齐 CNT == ARR-1 、 CNT==1

4. STM32 定时器相关寄存器

(1)TIMx_CR1 设置ARR寄存器是否有缓冲、关闭/开启计数器

位7:ARPE: 自动重载预装载使能(Auto-reload preload enable)
  • 0: TIMx_ARR寄存器没有缓冲,默认值,赋值后立即将ARR的值加载到影子寄存器
  • 1: TIMx_ARR寄存器有缓冲,在更新事件时自动将ARR的值加载到影子寄存器
位0:CEN:计数器使能(Counter enable)
  • 0:关闭计数器
  • 1: 使能计数器

(2)TIMx_DIER

位8: UDE:更新DMA请求使能(Update DMA request enable)
  • 0:关闭DMA请求
  • 1: 使能DMA请求
位0:UIE:更新中断使能(Update interrupt enable)
  • 0:关闭更新中断
  • 1: 使能更新中断

(3)TIMx_SR 状态寄存器

位0: UIF:更新中断标志(Update interrupt flag)
  • 0:无更新中断
  • 1: 有更新中断

在中断服务函数中,需要手动清除中断标志位,否则会一直触发中断。

(4)TIMx_CNT 计数器寄存器

  • 位宽为16位,用于存储计数器的值。

(5)TIMx_PSC 预分频器寄存器

  • 位宽为16位,用于设置预分频器的值。
  • 计数器的时钟频率 = 定时器时钟频率 / (预分频器值 + 1)。

(6)TIMx_ARR 自动重装载寄存器

  • 位宽为16位,用于设置计数器的上限值。
  • 当计数器的值达到 ARR 中设置的值时,会产生更新事件,计数器会重新归零。
  • 如果自动重装载值为0,则计数器停止 。

5. 定时器溢出时间计算方法

定时器溢出时间 T o u t =(自动重装载值ARR+1)∗(预分频系数PSC+1)/定时器时钟频率 F t 定时器溢出时间T_{out} = (自动重装载值ARR + 1) * (预分频系数PSC + 1) / 定时器时钟频率F_t 定时器溢出时间Tout=(自动重装载值ARR+1(预分频系数PSC+1/定时器时钟频率Ft

三、定时器配置步骤

1. 配置定时器基础工作参数

HAL_TIM_Base_Init(&htim);

2. 定时器基础MSP初始化

HAL_TIM_Base_MspInit(&htim); 配置NVIC,CLOCK等, GPIO配置

3. 使能更新中断并启动计数器

HAL_TIM_Base_Start_IT(&htim);

4. 设置优先级,使能中断

HAL_NVIC_SetPriority(TIMx_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIMx_IRQn);

5. 编写中断服务函数

void TIMx_IRQHandler(void)

6. 清除中断标志位

__HAL_TIM_CLEAR_IT(&htim, TIM_IT_UPDATE);

另外有一个定时器更新中断回调函数,在中断服务函数中会自动调用,该函数用户可以自行重写:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);

四、定时器配置实例

本示例使用定时器6,实现500ms定时器更新中断,控制GPIO口翻转。本项目在之前项目基础上增加配置,省略了GPIO等配置说明 。
时钟频率设置如下:
STM32 HAL库开发学习13. 定时器及基本定时器使用_stm32定时器hal库

1. STM32CubeMX配置 启用TIM6

STM32 HAL库开发学习13. 定时器及基本定时器使用_stm32定时器hal库
超时时间=(499+1)*(7999+1)/8MHz = 500ms。

2. 启动 TIM6全局中断

STM32 HAL库开发学习13. 定时器及基本定时器使用_stm32定时器hal库

3. 生成的部分代码

main.c里TIM6初始化

/** * @brief TIM6 Initialization Function * @param None * @retval None */static void MX_TIM6_Init(void){ /* USER CODE BEGIN TIM6_Init 0 */ /* USER CODE END TIM6_Init 0 */ TIM_MasterConfigTypeDef sMasterConfig = {0}; /* USER CODE BEGIN TIM6_Init 1 */ /* USER CODE END TIM6_Init 1 */ htim6.Instance = TIM6; htim6.Init.Prescaler = 7999; htim6.Init.CounterMode = TIM_COUNTERMODE_UP; htim6.Init.Period = 499; htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; if (HAL_TIM_Base_Init(&htim6) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM6_Init 2 */ /* USER CODE END TIM6_Init 2 */}

stm32f1xx_it.c 中断

/** * @brief This function handles TIM6 global interrupt. */void TIM6_IRQHandler(void){ /* USER CODE BEGIN TIM6_IRQn 0 */ /* USER CODE END TIM6_IRQn 0 */ HAL_TIM_IRQHandler(&htim6); /* USER CODE BEGIN TIM6_IRQn 1 */ /* USER CODE END TIM6_IRQn 1 */}

4. 手工添加代码

(1)TIM6初始化的代码里,添加启动中断

/* 在TIM6初始化函数末尾添加 *//* USER CODE BEGIN TIM6_Init 2 */HAL_TIM_Base_Start_IT(&htim6); // 启动定时器中断/* USER CODE END TIM6_Init 2 */

(2)实现中断回调函数

/* 定时器6中断回调 */void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(htim->Instance == TIM6) { // 这里添加中断处理代码 HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_0); }}