Skip to content

2.4 定时器中断

TIM 定时器分类

基本定时器

  • 预分频、自动装载值、自定义计数方向、自定义触发事件

  • 单个脉冲输出

  • 可以产生 DMA 请求定期搬运数据(DMA 在 UART 章节会提到)

通用定时器

  • 基本定时器的全部功能
  • 四个独立 GPIO 通道可以进行输入捕获、输出比较、PWM 生成、编码器模式等

高级定时器

  • 通用定时器的全部功能
  • 八个 GPIO 通道可以支持反向或互补 PWM 输出
  • 一个 GPIO 通道可以支持外部输入信号引入刹车重启等功能

其他常用功能

预分频(Prescaler,PSC)

  • 定时器输入频率从时钟树上的 APB 总线获取,但定时器本身可能不需要太高频率,因此需要对定时器输入频率进行分频,得到定时器的主频

计数模式

  • 定时器有个计数器(Counter,CNT根据其主频每产生一次脉冲,计数器改变 1

  • 向上计数,则 + 1;向下计数,则 - 1,双向计数则既可以 + 1 也可以 - 1

自动装载值(Auto Reload Register,ARR)

  • 定时器的计数器只能在 0 到 ARR 之间变动
  • 向上计数,则从 0 计数到 ARR,然后再开启一轮循环
  • 向下计数,则从 ARR 计数到 0,然后再开启一轮循环
  • 双向计数,则从 0 计数到 ARR-1,然后再从 ARR 计数到 1,然后再开启一轮循环
  • 当计数器向上到达 ARR 或向下到达 0 时,下一个定时器主频周期会产生溢出中断

Delay 函数

  • Hal 库利用 SysTick 定期维护变量 uwTick 以实现计时功能

  • 一般只在 main 中使用,不建议在中断中使用

配置定时器

  • 配置 RCC-HSE 为外部晶振
  • 配置时钟树 HSE 输出主频 50MHz(便于后续计算)
  • 配置定时器 TIMx
    • 设定为内部时钟 并调整 PSC 与 ARR
    • 溢出事件频率 frequency=(mainfrequency)((PSC+1)(ARR+1))

使用 TIM 定时器

使能定时器中断 Hal_TIM_Base_Start_IT(&htimx);

定义中断回调函数的实函数

c
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim == &htim5) {
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_5);
    }
}

利用 TIM 定时器中断实现按键检测消抖

1. 修改定时器配置

HSE 输出主频 50MHz

PSC:999

ARR:499

此时检测频率为 10ms

2. 修改按键配置

依据原理图定义相关按键为上拉输入

3. 代码部分

同上使能定时器中断,并定义实函数

C
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim == &htim5) {
        static GPIO_PinState pre_status =
            GPIO_PIN_SET; // 记录上次检测时的电平状态
        GPIO_PinState now_status = HAL_GPIO_ReadPin(
            GPIOE, GPIO_PIN_3); // 记录此次检测时的电平状态
        if (pre_status == GPIO_PIN_SET && now_status == GPIO_PIN_RESET) {
            /* 	当上次为高电平(未被按下)
                且此次为低电平(已被按下)*/
            HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_5); // 反转LED电平
        }
        pre_status = now_status; // 更新记录的电平状态
    }
}