嵌入式MCU的中断系统工作流程及其原理
2026/5/16 19:44:28 网站建设 项目流程



哈哈,这个问题非常经典,也是很多嵌入式新手和老鸟都很关心的坑。我们就用STM32F103C8T6来讲,顺便解释底层原理。咱一步步分析。


1️⃣ 场景设定

  • 定时器:10ms 自动重装载(ARR),也就是每 10ms 触发一次中断。
  • ISR 内容:里面做了大量操作 + 延时,总共耗时 1.3 秒(1300ms)。
  • CPU:STM32F103C8T6 是 Cortex-M3,单核,单线程,没有操作系统。

2️⃣ STM32 中断基本规则

  • Cortex-M3 内核中断嵌套是允许的,但有条件:

    • 默认同优先级中断不嵌套
    • 高优先级中断可以打断低优先级中断
  • 同一个定时器的中断默认同优先级,也就是:

    • 如果前一次中断还在执行,下一次中断触发时不会立即执行 ISR。
    • 内核会把“中断挂起”状态标记为pending
    • ISR 执行完之后,CPU 才会去处理 pending 的中断。

3️⃣ 你这个例子会发生什么

情况:
  1. 第一次中断触发:

    • ISR 开始执行,执行了 1.3 秒。
  2. 10ms 后,定时器再次到期:

    • 中断挂起标志被设置(pending)。
    • ISR还没结束,所以这次中断不会立即打断 ISR。
  3. ISR 执行完 1.3 秒后:

    • CPU 会检测到 pending 标志。
    • ISR 会立即被再次执行一次。
  4. 期间定时器继续计数:

    • 如果 10ms 又触发,pending 标志再次置位。
    • ISR 结束后又会再次执行。

⚠️结果:ISR 永远跑不完“实时”,定时器节奏完全失效


4️⃣ 实际影响总结

影响解释
定时器无法保持准确周期ISR 太长导致定时事件被积压,每次执行完 ISR 才处理下一次,周期不再是 10ms,而是 1.3s+积压次数
系统响应变慢CPU 被 ISR 占满,其他任务几乎无机会执行(特别是没有 RTOS)
堆积中断 pending如果 ISR 内部又有延时,可能造成更严重的“卡死”
可能触发 watchdog 重置MCU 的看门狗可能认为系统“死循环”

5️⃣ 解决方案建议

  1. 不要在定时器 ISR 里做耗时操作

    • ISR 里只做标记、采样、清计数器等轻量操作
    • 把重任务放在主循环或者 RTOS 任务里执行。
    volatileuint8_tflag=0;voidTIMx_IRQHandler(void){if(TIM_GetITStatus(TIMx,TIM_IT_Update)!=RESET){TIM_ClearITPendingBit(TIMx,TIM_IT_Update);flag=1;// 只设置标志}}intmain(void){while(1){if(flag){flag=0;heavy_processing();// 耗时操作放主循环}}}
  2. 缩短 ISR 执行时间

    • ISR 内不要调用delay(),不要打印日志。
    • 只处理必要硬件操作。
  3. 使用 RTOS 任务代替

    • 定时器 ISR 发信号/设置标志。
    • 重任务在低优先级任务中执行。
    • 保证高优先级 ISR 快速退出,防止打断积压。

💡总结一句话:

在 STM32 上,如果 ISR 执行时间远超定时周期,定时器中断会积压,系统节奏彻底失效,而且可能让 MCU 看起来“卡死”。


我可以帮你画一张“ISR 太长导致中断积压的时间轴图”,用 STM32 的例子标注 pending 状态,非常直观。
你想要我画吗?




好啊,这个概念在 Cortex-M 系列 MCU 上很关键,也和你之前提的“ISR 太长”问题直接相关。咱用STM32F103C8T6(Cortex-M3)来讲。


1️⃣ 中断嵌套(Nested Interrupt)是什么?

中断嵌套就是:

当一个中断正在执行时,如果另一个中断发生,并且优先级比当前中断高,CPU 可以“打断”当前中断去处理新的高优先级中断,处理完再回来继续执行原来的中断。

简单比喻:

  • 你正在厨房煮饭(中断A正在执行)
  • 电话响了(中断B发生)
  • 如果电话比饭重要(中断B优先级更高),你先接电话,接完再回来继续煮饭

2️⃣ Cortex-M3 的中断嵌套机制

STM32F103C8T6 是Cortex-M3,它有一个叫NVIC(Nested Vectored Interrupt Controller)的中断控制器。

NVIC 特性:
  • 支持优先级分组:可以配置 preemption 优先级和子优先级

  • 当 ISR 执行时:

    • 如果新中断优先级高→ ISR 被“打断”,执行高优先级 ISR
    • 如果新中断优先级低或相同→ 挂起,等当前 ISR 结束再处理
默认行为:
  • 同一个定时器的中断默认同优先级
  • 所以 ISR 执行时,下一次中断不会立即打断,必须等 ISR 结束

3️⃣ 实例说明

假设:

  • TIM2 中断优先级 = 2
  • USART1 中断优先级 = 1 (更高)

时间轴:

t=0ms: TIM2 中断触发 → ISR_TIM2 开始 t=1ms: USART1 接收到数据 → ISR_USART1 打断 ISR_TIM2 t=1.5ms: ISR_USART1 执行完 → 返回 ISR_TIM2 t=... 继续执行 ISR_TIM2

⚠️ 如果 TIM2 和 USART1同优先级

t=0ms: TIM2 ISR开始 t=10ms: TIM2 再次触发 → 设 pending t=1300ms: ISR_TIM2 结束 → CPU 检查 pending → 再执行 ISR_TIM2

✅ 这个就是你前面说的“ISR太长导致中断积压”的典型场景


4️⃣ 为什么要中断嵌套?

  • 高优先级任务快速响应

    • 例如:电机过流保护、紧急停止信号必须立刻处理
  • 实时性保证

    • 允许关键中断不被低优先级中断拖慢

5️⃣ 注意事项

  1. 嵌套会增加栈使用

    • 每个 ISR 都会把寄存器压入栈
    • 嵌套太深 → 可能造成栈溢出
  2. ISR 仍要尽量短:

    • 即使支持嵌套,也不意味着可以在 ISR 内做“1.3秒处理”
  3. 优先级分组设置:

    • Cortex-M3 可以划分 preemption 优先级和子优先级
    • 决定哪些中断可以打断哪些

💡 小总结:

  • 中断嵌套 = 高优先级 ISR 可以打断低优先级 ISR
  • 同优先级 ISR 不会打断自己 → 累积 pending
  • ISR 太长 → 定时器节奏彻底失效 → 可能让系统“卡死”

如果你愿意,我可以帮你画一张Cortex-M3 中断嵌套示意图,直观地看到 pending、打断、返回的过程,非常容易理解。

你想让我画吗?




好,这个问题非常关键,你问的正是 STM32/Cortex-M 系列 MCU中断底层执行流程的核心,理解了这些,ISR 太长、嵌套、挂起这些问题就都能看明白了。咱用STM32F103C8T6(Cortex-M3)来讲。


1️⃣ 中断挂起(Pending)标志位什么时候清除?

每个中断在NVIC外设寄存器里都有一个挂起标志(Pending Bit),它的作用是记录“这个中断已经触发了,但还没被处理”。

清除时机:

  1. 手动清除(软件清除)

    • 大多数 STM32 外设都有中断挂起清除寄存器(例如TIMx->SRUIF位)。
    • ISR 内通常第一步就是清除这个标志,否则同一次中断会被“反复触发”。
    voidTIM2_IRQHandler(void){if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET){TIM_ClearITPendingBit(TIM2,TIM_IT_Update);// 清除挂起标志// 用户处理代码}}
  2. 自动清除

    • 某些外设中断,例如 STM32F1 的 EXTI(外部中断),某些配置下可以硬件自动清除。
    • 大多数情况下还是软件清除更安全

⚠️如果不清除挂起位

  • ISR 执行完后 NVIC 会发现挂起位仍然置位 → ISR 会立即再次执行 → 造成“无限循环”中断

2️⃣ Cortex-M3 中断处理流程(简化版)

假设外设 TIM2 触发中断:

1️⃣ 中断触发 - 外设产生中断请求 - 对应的 NVIC Pending 位被置 1 2️⃣ NVIC 响应中断 - CPU 检查中断优先级 - 如果当前没有更高优先级的 ISR 在执行 → 准备进入 ISR 3️⃣ ISR 入口(硬件自动操作) - 自动保存寄存器 r0-r3, r12, lr, pc, xPSR 到栈 - PC 跳转到 ISR 入口地址 4️⃣ ISR 执行(软件操作) - 用户代码开始执行 - **第一步通常清除中断挂起标志** - 执行实际业务逻辑(采样、标志置位、发送数据等) 5️⃣ ISR 退出(硬件自动操作) - 执行 `BX LR` 返回 - Cortex-M3 自动弹出栈上的寄存器 - 如果有 pending 中断且优先级合适 → CPU 自动跳转去处理 6️⃣ 返回主程序或下一个中断

3️⃣ 图示化理解

时间轴 (ms) |---------------------------| t=0 TIM2中断触发 → pending=1 t=0.1 CPU进入ISR t=0.1~0.2 ISR执行 → 清除挂起标志 t=0.2 ISR结束 → 栈恢复,pending=0 t=0.25 有其他中断触发

注意点:

  • 挂起标志位必须清除,否则 ISR 会重复执行
  • NVIC 会根据优先级决定是否立即打断当前 ISR
  • 嵌套中断会增加栈使用,深度太深可能溢出

💡总结一句话

中断挂起标志位在 ISR 执行期间由软件(通常第一步)清除,清除后 ISR 才能顺利退出;CPU 执行中断时,硬件自动保存现场,处理完 ISR 再恢复现场,检查是否有 pending 中断并决定是否立即进入下一次中断。


我可以帮你画一张STM32F1 中断执行+挂起标志清除的流程图,能直观看到 pending、NVIC、ISR 执行顺序,非常容易理解。

你想让我画吗?

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询