1. 本课目标
- 理解定时器相对阻塞式延时的优势。
- 理解 PSC、ARR、CNT 和更新事件。
- 根据公式计算定时器周期。
- 理解 TIM2 更新中断和 NVIC 的关系。
- 读懂
TIM2_IRQHandler()。
2. 知识主线
#mermaid-svg-I3eTuLDvzAog1QWo{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-I3eTuLDvzAog1QWo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-I3eTuLDvzAog1QWo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-I3eTuLDvzAog1QWo .error-icon{fill:#552222;}#mermaid-svg-I3eTuLDvzAog1QWo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-I3eTuLDvzAog1QWo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-I3eTuLDvzAog1QWo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-I3eTuLDvzAog1QWo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-I3eTuLDvzAog1QWo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-I3eTuLDvzAog1QWo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-I3eTuLDvzAog1QWo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-I3eTuLDvzAog1QWo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-I3eTuLDvzAog1QWo .marker.cross{stroke:#333333;}#mermaid-svg-I3eTuLDvzAog1QWo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-I3eTuLDvzAog1QWo p{margin:0;}#mermaid-svg-I3eTuLDvzAog1QWo .edge{stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .section--1 rect,#mermaid-svg-I3eTuLDvzAog1QWo .section--1 path,#mermaid-svg-I3eTuLDvzAog1QWo .section--1 circle,#mermaid-svg-I3eTuLDvzAog1QWo .section--1 polygon,#mermaid-svg-I3eTuLDvzAog1QWo .section--1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .section--1 text{fill:#ffffff;}#mermaid-svg-I3eTuLDvzAog1QWo .node-icon--1{font-size:40px;color:#ffffff;}#mermaid-svg-I3eTuLDvzAog1QWo .section-edge--1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .edge-depth--1{stroke-width:17;}#mermaid-svg-I3eTuLDvzAog1QWo .section--1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled,#mermaid-svg-I3eTuLDvzAog1QWo .disabled circle,#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:lightgray;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:#efefef;}#mermaid-svg-I3eTuLDvzAog1QWo .section-0 rect,#mermaid-svg-I3eTuLDvzAog1QWo .section-0 path,#mermaid-svg-I3eTuLDvzAog1QWo .section-0 circle,#mermaid-svg-I3eTuLDvzAog1QWo .section-0 polygon,#mermaid-svg-I3eTuLDvzAog1QWo .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-I3eTuLDvzAog1QWo .section-0 text{fill:black;}#mermaid-svg-I3eTuLDvzAog1QWo .node-icon-0{font-size:40px;color:black;}#mermaid-svg-I3eTuLDvzAog1QWo .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-I3eTuLDvzAog1QWo .edge-depth-0{stroke-width:14;}#mermaid-svg-I3eTuLDvzAog1QWo .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled,#mermaid-svg-I3eTuLDvzAog1QWo .disabled circle,#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:lightgray;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:#efefef;}#mermaid-svg-I3eTuLDvzAog1QWo .section-1 rect,#mermaid-svg-I3eTuLDvzAog1QWo .section-1 path,#mermaid-svg-I3eTuLDvzAog1QWo .section-1 circle,#mermaid-svg-I3eTuLDvzAog1QWo .section-1 polygon,#mermaid-svg-I3eTuLDvzAog1QWo .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .section-1 text{fill:black;}#mermaid-svg-I3eTuLDvzAog1QWo .node-icon-1{font-size:40px;color:black;}#mermaid-svg-I3eTuLDvzAog1QWo .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .edge-depth-1{stroke-width:11;}#mermaid-svg-I3eTuLDvzAog1QWo .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled,#mermaid-svg-I3eTuLDvzAog1QWo .disabled circle,#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:lightgray;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:#efefef;}#mermaid-svg-I3eTuLDvzAog1QWo .section-2 rect,#mermaid-svg-I3eTuLDvzAog1QWo .section-2 path,#mermaid-svg-I3eTuLDvzAog1QWo .section-2 circle,#mermaid-svg-I3eTuLDvzAog1QWo .section-2 polygon,#mermaid-svg-I3eTuLDvzAog1QWo .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .section-2 text{fill:#ffffff;}#mermaid-svg-I3eTuLDvzAog1QWo .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-I3eTuLDvzAog1QWo .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .edge-depth-2{stroke-width:8;}#mermaid-svg-I3eTuLDvzAog1QWo .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled,#mermaid-svg-I3eTuLDvzAog1QWo .disabled circle,#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:lightgray;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:#efefef;}#mermaid-svg-I3eTuLDvzAog1QWo .section-3 rect,#mermaid-svg-I3eTuLDvzAog1QWo .section-3 path,#mermaid-svg-I3eTuLDvzAog1QWo .section-3 circle,#mermaid-svg-I3eTuLDvzAog1QWo .section-3 polygon,#mermaid-svg-I3eTuLDvzAog1QWo .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .section-3 text{fill:black;}#mermaid-svg-I3eTuLDvzAog1QWo .node-icon-3{font-size:40px;color:black;}#mermaid-svg-I3eTuLDvzAog1QWo .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .edge-depth-3{stroke-width:5;}#mermaid-svg-I3eTuLDvzAog1QWo .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled,#mermaid-svg-I3eTuLDvzAog1QWo .disabled circle,#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:lightgray;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:#efefef;}#mermaid-svg-I3eTuLDvzAog1QWo .section-4 rect,#mermaid-svg-I3eTuLDvzAog1QWo .section-4 path,#mermaid-svg-I3eTuLDvzAog1QWo .section-4 circle,#mermaid-svg-I3eTuLDvzAog1QWo .section-4 polygon,#mermaid-svg-I3eTuLDvzAog1QWo .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .section-4 text{fill:black;}#mermaid-svg-I3eTuLDvzAog1QWo .node-icon-4{font-size:40px;color:black;}#mermaid-svg-I3eTuLDvzAog1QWo .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .edge-depth-4{stroke-width:2;}#mermaid-svg-I3eTuLDvzAog1QWo .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled,#mermaid-svg-I3eTuLDvzAog1QWo .disabled circle,#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:lightgray;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:#efefef;}#mermaid-svg-I3eTuLDvzAog1QWo .section-5 rect,#mermaid-svg-I3eTuLDvzAog1QWo .section-5 path,#mermaid-svg-I3eTuLDvzAog1QWo .section-5 circle,#mermaid-svg-I3eTuLDvzAog1QWo .section-5 polygon,#mermaid-svg-I3eTuLDvzAog1QWo .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .section-5 text{fill:black;}#mermaid-svg-I3eTuLDvzAog1QWo .node-icon-5{font-size:40px;color:black;}#mermaid-svg-I3eTuLDvzAog1QWo .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .edge-depth-5{stroke-width:-1;}#mermaid-svg-I3eTuLDvzAog1QWo .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled,#mermaid-svg-I3eTuLDvzAog1QWo .disabled circle,#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:lightgray;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:#efefef;}#mermaid-svg-I3eTuLDvzAog1QWo .section-6 rect,#mermaid-svg-I3eTuLDvzAog1QWo .section-6 path,#mermaid-svg-I3eTuLDvzAog1QWo .section-6 circle,#mermaid-svg-I3eTuLDvzAog1QWo .section-6 polygon,#mermaid-svg-I3eTuLDvzAog1QWo .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .section-6 text{fill:black;}#mermaid-svg-I3eTuLDvzAog1QWo .node-icon-6{font-size:40px;color:black;}#mermaid-svg-I3eTuLDvzAog1QWo .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .edge-depth-6{stroke-width:-4;}#mermaid-svg-I3eTuLDvzAog1QWo .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled,#mermaid-svg-I3eTuLDvzAog1QWo .disabled circle,#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:lightgray;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:#efefef;}#mermaid-svg-I3eTuLDvzAog1QWo .section-7 rect,#mermaid-svg-I3eTuLDvzAog1QWo .section-7 path,#mermaid-svg-I3eTuLDvzAog1QWo .section-7 circle,#mermaid-svg-I3eTuLDvzAog1QWo .section-7 polygon,#mermaid-svg-I3eTuLDvzAog1QWo .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .section-7 text{fill:black;}#mermaid-svg-I3eTuLDvzAog1QWo .node-icon-7{font-size:40px;color:black;}#mermaid-svg-I3eTuLDvzAog1QWo .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .edge-depth-7{stroke-width:-7;}#mermaid-svg-I3eTuLDvzAog1QWo .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled,#mermaid-svg-I3eTuLDvzAog1QWo .disabled circle,#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:lightgray;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:#efefef;}#mermaid-svg-I3eTuLDvzAog1QWo .section-8 rect,#mermaid-svg-I3eTuLDvzAog1QWo .section-8 path,#mermaid-svg-I3eTuLDvzAog1QWo .section-8 circle,#mermaid-svg-I3eTuLDvzAog1QWo .section-8 polygon,#mermaid-svg-I3eTuLDvzAog1QWo .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .section-8 text{fill:black;}#mermaid-svg-I3eTuLDvzAog1QWo .node-icon-8{font-size:40px;color:black;}#mermaid-svg-I3eTuLDvzAog1QWo .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .edge-depth-8{stroke-width:-10;}#mermaid-svg-I3eTuLDvzAog1QWo .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled,#mermaid-svg-I3eTuLDvzAog1QWo .disabled circle,#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:lightgray;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:#efefef;}#mermaid-svg-I3eTuLDvzAog1QWo .section-9 rect,#mermaid-svg-I3eTuLDvzAog1QWo .section-9 path,#mermaid-svg-I3eTuLDvzAog1QWo .section-9 circle,#mermaid-svg-I3eTuLDvzAog1QWo .section-9 polygon,#mermaid-svg-I3eTuLDvzAog1QWo .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .section-9 text{fill:black;}#mermaid-svg-I3eTuLDvzAog1QWo .node-icon-9{font-size:40px;color:black;}#mermaid-svg-I3eTuLDvzAog1QWo .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .edge-depth-9{stroke-width:-13;}#mermaid-svg-I3eTuLDvzAog1QWo .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled,#mermaid-svg-I3eTuLDvzAog1QWo .disabled circle,#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:lightgray;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:#efefef;}#mermaid-svg-I3eTuLDvzAog1QWo .section-10 rect,#mermaid-svg-I3eTuLDvzAog1QWo .section-10 path,#mermaid-svg-I3eTuLDvzAog1QWo .section-10 circle,#mermaid-svg-I3eTuLDvzAog1QWo .section-10 polygon,#mermaid-svg-I3eTuLDvzAog1QWo .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .section-10 text{fill:black;}#mermaid-svg-I3eTuLDvzAog1QWo .node-icon-10{font-size:40px;color:black;}#mermaid-svg-I3eTuLDvzAog1QWo .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .edge-depth-10{stroke-width:-16;}#mermaid-svg-I3eTuLDvzAog1QWo .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled,#mermaid-svg-I3eTuLDvzAog1QWo .disabled circle,#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:lightgray;}#mermaid-svg-I3eTuLDvzAog1QWo .disabled text{fill:#efefef;}#mermaid-svg-I3eTuLDvzAog1QWo .section-root rect,#mermaid-svg-I3eTuLDvzAog1QWo .section-root path,#mermaid-svg-I3eTuLDvzAog1QWo .section-root circle,#mermaid-svg-I3eTuLDvzAog1QWo .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-I3eTuLDvzAog1QWo .section-root text{fill:#ffffff;}#mermaid-svg-I3eTuLDvzAog1QWo .section-root span{color:#ffffff;}#mermaid-svg-I3eTuLDvzAog1QWo .section-2 span{color:#ffffff;}#mermaid-svg-I3eTuLDvzAog1QWo .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-I3eTuLDvzAog1QWo .edge{fill:none;}#mermaid-svg-I3eTuLDvzAog1QWo .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-I3eTuLDvzAog1QWo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} TIM2 定时器中断
时钟
RCC_APB1PeriphClockCmd
TIM2
APB1
定时器时钟
时基单元
PSC 预分频器
ARR 自动重装
CNT 计数器
向上计数
中断
更新事件
TIM_IT_Update
TIM2_IRQHandler
清除标志位
NVIC
中断通道
抢占优先级
响应优先级
通道使能
程序分工
主循环刷新 OLED
中断更新 Num
验证边界
依赖系统时钟
需要编译验证
需要硬件或仿真验证
3. 主程序
c
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
uint16_t Num;
int main(void)
{
OLED_Init();
Timer_Init();
OLED_ShowString(1, 1, "Num:");
while (1)
{
// 主循环负责刷新显示,中断负责更新 Num
OLED_ShowNum(1, 5, Num, 5);
}
}
程序采用"中断更新数据、主循环显示数据"的分工:
text
TIM2 中断 -> Num++
主循环 -> OLED 显示 Num
4. TIM2 初始化
c
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);
}
5. 定时器的工作过程
text
定时器输入时钟
-> PSC 分频
-> CNT 计数
-> 达到 ARR
-> 产生更新事件
-> 触发 TIM2 更新中断
5.1 预分频器 PSC
c
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
计数频率公式:
text
计数频率 = 定时器输入时钟 / (PSC + 1)
若 TIM2 输入时钟为 72 MHz:
text
72,000,000 / 7200 = 10,000 Hz
即每 0.1 ms 计数一次。
5.2 自动重装值 ARR
c
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
计数器向上计数:
text
0, 1, 2, ..., 9999
共计数 10000 次,因此:
text
10000 × 0.1 ms = 1000 ms = 1 s
6. 定时器周期公式
text
更新事件频率 = 定时器时钟 / ((PSC + 1) × (ARR + 1))
本工程在定时器时钟为 72 MHz 的假设下:
text
72,000,000 / (7200 × 10000) = 1 Hz
所以更新中断理论周期约为 1 秒,Num 理论上每秒加 1。
STM32F1 的 APB1 和定时器时钟存在倍频规则,不能只看 APB1 总线频率。必须结合工程的 RCC 和 SystemInit() 配置确认实际定时器输入时钟。
7. 为什么参数减 1
寄存器实际含义是:
text
分频系数 = PSC + 1
计数次数 = ARR + 1
因此希望分频 7200、计数 10000 次时,应写:
c
PSC = 7200 - 1;
ARR = 10000 - 1;
8. 更新中断与 NVIC
开启 TIM2 内部更新中断:
c
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
配置 CPU 的中断控制器:
c
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
两层使能缺一不可:
text
TIM_ITConfig -> TIM2 外设允许产生中断
NVIC_Init -> CPU 允许接收 TIM2 中断线路
抢占优先级决定一个中断能否打断另一个中断;响应优先级用于多个等待中断之间的先后判断。
9. 中断处理函数
c
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
Num++;
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
函数名必须与启动文件中的中断向量名称完全一致。TIM2_IRQHandler 不能改成自定义名称,否则 CPU 不会自动跳转到该函数。
进入中断后必须清除更新中断标志,否则中断请求可能持续有效,导致 CPU 反复进入中断函数,主程序表现为卡死或无法正常运行。
10. 程序流程图
#mermaid-svg-kjyfUuNXNwis1KTG{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kjyfUuNXNwis1KTG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kjyfUuNXNwis1KTG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kjyfUuNXNwis1KTG .error-icon{fill:#552222;}#mermaid-svg-kjyfUuNXNwis1KTG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kjyfUuNXNwis1KTG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kjyfUuNXNwis1KTG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kjyfUuNXNwis1KTG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kjyfUuNXNwis1KTG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kjyfUuNXNwis1KTG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kjyfUuNXNwis1KTG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kjyfUuNXNwis1KTG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kjyfUuNXNwis1KTG .marker.cross{stroke:#333333;}#mermaid-svg-kjyfUuNXNwis1KTG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kjyfUuNXNwis1KTG p{margin:0;}#mermaid-svg-kjyfUuNXNwis1KTG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kjyfUuNXNwis1KTG .cluster-label text{fill:#333;}#mermaid-svg-kjyfUuNXNwis1KTG .cluster-label span{color:#333;}#mermaid-svg-kjyfUuNXNwis1KTG .cluster-label span p{background-color:transparent;}#mermaid-svg-kjyfUuNXNwis1KTG .label text,#mermaid-svg-kjyfUuNXNwis1KTG span{fill:#333;color:#333;}#mermaid-svg-kjyfUuNXNwis1KTG .node rect,#mermaid-svg-kjyfUuNXNwis1KTG .node circle,#mermaid-svg-kjyfUuNXNwis1KTG .node ellipse,#mermaid-svg-kjyfUuNXNwis1KTG .node polygon,#mermaid-svg-kjyfUuNXNwis1KTG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kjyfUuNXNwis1KTG .rough-node .label text,#mermaid-svg-kjyfUuNXNwis1KTG .node .label text,#mermaid-svg-kjyfUuNXNwis1KTG .image-shape .label,#mermaid-svg-kjyfUuNXNwis1KTG .icon-shape .label{text-anchor:middle;}#mermaid-svg-kjyfUuNXNwis1KTG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kjyfUuNXNwis1KTG .rough-node .label,#mermaid-svg-kjyfUuNXNwis1KTG .node .label,#mermaid-svg-kjyfUuNXNwis1KTG .image-shape .label,#mermaid-svg-kjyfUuNXNwis1KTG .icon-shape .label{text-align:center;}#mermaid-svg-kjyfUuNXNwis1KTG .node.clickable{cursor:pointer;}#mermaid-svg-kjyfUuNXNwis1KTG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kjyfUuNXNwis1KTG .arrowheadPath{fill:#333333;}#mermaid-svg-kjyfUuNXNwis1KTG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kjyfUuNXNwis1KTG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kjyfUuNXNwis1KTG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kjyfUuNXNwis1KTG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kjyfUuNXNwis1KTG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kjyfUuNXNwis1KTG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kjyfUuNXNwis1KTG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kjyfUuNXNwis1KTG .cluster text{fill:#333;}#mermaid-svg-kjyfUuNXNwis1KTG .cluster span{color:#333;}#mermaid-svg-kjyfUuNXNwis1KTG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kjyfUuNXNwis1KTG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kjyfUuNXNwis1KTG rect.text{fill:none;stroke-width:0;}#mermaid-svg-kjyfUuNXNwis1KTG .icon-shape,#mermaid-svg-kjyfUuNXNwis1KTG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kjyfUuNXNwis1KTG .icon-shape p,#mermaid-svg-kjyfUuNXNwis1KTG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kjyfUuNXNwis1KTG .icon-shape .label rect,#mermaid-svg-kjyfUuNXNwis1KTG .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kjyfUuNXNwis1KTG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kjyfUuNXNwis1KTG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kjyfUuNXNwis1KTG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
是
复位进入 main
OLED_Init
Timer_Init
打开 TIM2 时钟
配置 PSC 和 ARR
开启更新中断
配置 NVIC
启动 TIM2
主循环刷新 OLED
TIM2 自动计数
计数达到 ARR?
产生更新中断
TIM2_IRQHandler
Num++
清除更新中断标志
11. 易错点
TIM_ITConfig()和NVIC_Init()是两层不同的中断使能。- 中断函数必须使用启动文件规定的准确名称。
- 进入中断后必须清除更新中断标志。
PSC和ARR的实际系数都要加 1。- 不能只凭经验假设定时器时钟是 72 MHz。
- 中断函数应尽量短,不应放入复杂 OLED 刷新或长时间延时。
Num被主循环和中断共同访问,复杂场景应考虑volatile和原子访问问题。
12. 事实与验证边界
- 已知事实:源码使用 TIM2,配置
PSC = 7200 - 1、ARR = 10000 - 1,开启更新中断并在中断中执行Num++。 - 合理推断:若 TIM2 输入时钟为 72 MHz 且初始化成功,更新中断理论周期约为 1 秒。
- 尚未确认:本次没有实际编译输出、OLED 显示结果或硬件/仿真中
Num变化的证据。
13. 课后思考
- 如果 ARR 改为
5000 - 1,在其他条件不变时中断周期是多少? - 如果希望中断周期为 10 ms,可以怎样选择 PSC 和 ARR?
- 为什么 OLED 刷新放在主循环,而不是放进 TIM2 中断函数?
- 忘记清除中断标志可能造成什么现象?
14. 下一步
后续可以学习定时器输出比较、PWM,或者把按键扫描改造成由定时器周期驱动的非阻塞状态机。