定时器(TIM)是STM32最常用的外设之一,用于计时、PWM生成、输入捕获等场景。本教程以TIM3为例,演示标准库配置步骤(基于STM32F10x系列)。

一、定时器核心概念

  1. 时钟源

    • 内部时钟(常用):APB1(TIM2/3/4)或APB2(TIM1/8)

    • 本例使用APB1(默认72MHz,若分频系数≠1则频率×2)

  2. 关键参数

    • 预分频器(PSC):降低输入时钟频率

    • 自动重装载值(ARR):计数上限(定时周期)

    • 计数模式:向上(常用)、向下、中央对齐

二、配置步骤(以1ms定时中断为例)

1. 使能时钟

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 开启TIM3时钟

2. 配置时基结构体

TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
TIM_TimeBaseStruct.TIM_Prescaler = 7200 - 1;    // 预分频值:72MHz/7200 = 10KHz
TIM_TimeBaseStruct.TIM_Period = 10000 - 1;       // 自动重载值:10KHz/10000 = 1Hz (1ms)
TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;     // 时钟分频(无关)
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct);     // 初始化TIM3

3. 使能定时器中断

TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); // 允许更新事件中断

4. 配置NVIC(嵌套向量中断控制器)

NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;      // TIM3中断通道
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;    // 子优先级
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;       // 使能通道
NVIC_Init(&NVIC_InitStruct);

5. 启动定时器

TIM_Cmd(TIM3, ENABLE); // 启动TIM3

三、编写中断服务函数

void TIM3_IRQHandler(void) {
  if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { // 检查中断标志
    // 用户代码区(例如:翻转LED)
    TIM_ClearITPendingBit(TIM3, TIM_IT_Update); // 清除中断标志
  }
}

四、关键函数说明

函数原型 作用
TIM_TimeBaseInit(TIMx, &initStruct) 初始化定时器时基参数
TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE) 使能指定中断类型
TIM_Cmd(TIMx, ENABLE) 启动/停止定时器
TIM_GetITStatus(TIMx, TIM_IT_Update) 获取中断状态
TIM_ClearITPendingBit(TIMx, TIM_IT_Update) 清除中断标志

五、常见问题

  1. 定时不准?

    • 检查系统时钟配置(SystemInit()是否调用)

    • 确认APB总线时钟频率(通过RCC_GetClocksFreq()获取)

  2. 无中断触发?

    • 检查NVIC配置是否使能

    • 确认中断服务函数名拼写正确(如TIM3_IRQHandler

  3. PSC和ARR计算

    • 定时周期公式

      T定时=(PSC+1)×(ARR+1)T时钟T定时​=T时钟​(PSC+1)×(ARR+1)​
    • 例:1ms定时 @72MHz → PSC=7199ARR=9(计算:72e6 / (7200 * 10) = 1000Hz)

六、完整代码模板

#include "stm32f10x.h"

void TIM3_Init(void) {
  // 1. 时钟使能
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  
  // 2. 时基配置
  TIM_TimeBaseInitTypeDef TIM_InitStruct;
  TIM_InitStruct.TIM_Prescaler = 7200 - 1;      // 10KHz
  TIM_InitStruct.TIM_Period = 10000 - 1;         // 1ms
  TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseInit(TIM3, &TIM_InitStruct);
  
  // 3. 中断配置
  TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
  
  // 4. NVIC配置
  NVIC_InitTypeDef NVIC_InitStruct;
  NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStruct);
  
  // 5. 启动定时器
  TIM_Cmd(TIM3, ENABLE);
}

// 中断服务函数
void TIM3_IRQHandler(void) {
  if (TIM_GetITStatus(TIM3, TIM_IT_Update)) {
    // 用户逻辑(如:LED_Toggle())
    TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
  }
}

提示

  • 修改TIM_PrescalerTIM_Period可调整定时周期

  • 不同定时器对应不同中断向量(TIM1→TIM1_UP_IRQHandler

  • 标准库需包含头文件#include "stm32f10x_tim.h"

掌握定时器配置是STM32开发的基石!建议结合示波器调试实际波形,深入理解时序控制。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐