6. 定时器
📌 本节学习目标
- 了解 STM32 定时器分类与特性
- 掌握 SysTick 滴答定时器的使用
- 掌握通用定时器的定时中断配置
- 理解输入捕获的基本原理
6.1 定时器分类
STM32F103 有 3 种类型的定时器:
| 类型 | 数量 | 计时器位数 | 主要特性 |
|---|---|---|---|
| 高级定时器(TIM1) | 1 | 16 位 | PWM 互补输出、死区插入、刹车功能 |
| 通用定时器(TIM2/3/4) | 3 | 16 位 | 定时、输入捕获、输出比较、PWM |
| 基本定时器(TIM6/7) | 2 | 16 位 | 基础定时、DAC 触发 |
| SysTick | 1 | 24 位 | Cortex-M3 内核内置,常用作系统心跳 |
6.2 通用定时器原理
通用定时器内部包含:
- 计数器 (CNT):向上/向下/中心对齐计数
- 预分频器 (PSC):对时钟进行分频,分频范围 1~65536
- 自动重装寄存器 (ARR):计数上限
定时时间计算公式:
T = (PSC + 1) × (ARR + 1) / 定时器时钟频率
例如:APB1 时钟 36MHz,TIM2 获得 72MHz(APB1 预分频≠1 时翻倍),PSC=7199,ARR=999:
T = (7200 × 1000) / 72,000,000 = 0.1s = 100ms
6.3 SysTick 定时器
C 代码(SysTick 延时)
#include "stm32f10x.h"
static uint32_t TimingDelay;
// SysTick 初始化:每 1ms 中断一次
void SysTick_Init(void)
{
// SystemCoreClock = 72000000 (72MHz)
// 计数值 = 72000000 / 1000 = 72000
if (SysTick_Config(SystemCoreClock / 1000))
{
while (1); // 配置失败
}
}
// SysTick 中断服务函数
void SysTick_Handler(void)
{
if (TimingDelay > 0)
TimingDelay--;
}
// 毫秒延时函数
void delay_ms(uint32_t ms)
{
TimingDelay = ms;
while (TimingDelay != 0);
}
// 微秒延时(循环等待方式)
void delay_us(uint32_t us)
{
uint32_t i;
for (i = 0; i < us; i++)
{
// 约 1μs @72MHz(实际需微调)
__NOP(); __NOP(); __NOP();
}
}6.4 通用定时器中断示例
C 代码(TIM3 定时中断)
#include "stm32f10x.h"
// TIM3 初始化:100ms 定时中断
void TIM3_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// PSC=7199 -> 72MHz/(7199+1) = 10KHz = 0.1ms
// ARR=999 -> 0.1ms × 1000 = 100ms
TIM_TimeBaseStructure.TIM_Period = 999;
TIM_TimeBaseStructure.TIM_Prescaler = 7199;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); // 更新中断
TIM_Cmd(TIM3, ENABLE); // 启动定时器
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// TIM3 中断服务函数
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
// 每 100ms 执行的任务
GPIO_ToggleBits(GPIOB, GPIO_Pin_0);
}
}💡 这两段代码怎么用?
- SysTick 延时:设置
LOAD后倒数到 0 自动重装,中断里递减计数,主程序忙等——这就是实验 14 的delay_ms原理 - 通用定时器中断:核心是
PSC(分频) +ARR(周期),配合 NVIC 产生周期性中断,实验 13 就是用它翻转 LED - 定时时间公式
T = (PSC+1)×(ARR+1)/72MHz务必背熟,实验题常考「给定时长反推 PSC/ARR」