4. 中断使能与屏蔽:全局中断使能、局部中断使能、中断屏蔽寄存器操作

中断系统就像MCU的“紧急事务处理中心”。你想想看,CPU正在忙着算数据,突然外设说“我有急事”,这时候怎么响应?谁来批准?谁有权拒绝?

这就要靠中断的使能与屏蔽机制来管理了。说白了,就是一套“谁可以打断CPU”的权限系统。

4.1 全局中断使能——总开关

全局中断使能是整个中断系统的总闸。在ARM Cortex-M系列里,这个总闸叫PRIMASK寄存器。在51单片机里,它就是EA位。

我习惯把全局中断比作“公司大门”。门开着,所有员工(中断源)才能进来汇报工作。门关了,谁也别想进。

核心操作:

  • 使能全局中断:__enable_irq() 或 EA = 1
  • 关闭全局中断:__disable_irq() 或 EA = 0

我在项目中遇到过一个问题:某次调试电机驱动,PWM输出总是不稳定。查了半天,发现是全局中断被意外关闭了。从那以后,我每次在关键代码段前后都会检查全局中断状态。

4.2 局部中断使能——分开关

全局中断打开了,不代表所有中断都能响应。每个外设都有自己的“分开关”——局部中断使能位。

比如STM32的定时器,你要单独使能TIMx的更新中断、捕获中断等。这些使能位通常放在外设的DIER(中断使能寄存器)里。

// STM32 定时器中断使能示例
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);  // 使能更新中断
TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);     // 使能通道1捕获中断

局部中断使能的好处是精细控制。你想想看,一个定时器可能有十几个中断源,你不可能让它们全部触发CPU。只开你需要的,其他屏蔽掉,这样系统才干净。

层级 控制对象 典型寄存器 作用范围
全局 所有中断 PRIMASK / EA 整个CPU
外设级 单个外设 NVIC_ISER / IE寄存器 特定外设
事件级 具体中断事件 DIER / 外设使能位 单个中断源

4.3 中断屏蔽寄存器操作——精细控制

中断屏蔽寄存器(Mask Register)是更底层的控制手段。在Cortex-M内核里,有个叫BASEPRI的寄存器,它可以屏蔽掉优先级低于某个值的中断。

这有什么用?举个例子:你在处理一个时间要求极严的PWM控制任务,不希望被其他低优先级中断打断。这时候设置BASEPRI,只允许最高优先级的中断进来,其他统统屏蔽。

我的经验:在电机控制中,电流环中断通常设为最高优先级。我会在进入电流环前设置BASEPRI,屏蔽掉所有低于电流环优先级的中断,确保电流采样和PWM更新不被干扰。

// Cortex-M BASEPRI 操作示例
__set_BASEPRI(0x50);   // 屏蔽优先级大于0x50的中断
// ... 执行关键代码 ...
__set_BASEPRI(0);      // 恢复所有中断

4.4 中断使能与屏蔽的实战流程

在实际项目中,中断使能和屏蔽的操作顺序很重要。我见过不少新手上来就开全局中断,结果外设还没配置好,中断就来了,系统直接跑飞。

正确的流程应该是:

  1. 先配置外设——设置时钟、引脚、模式
  2. 再配置中断——设置优先级、使能局部中断
  3. 最后开全局中断——让系统开始响应

注意:千万不要在中断服务函数里长时间关闭全局中断。我曾经接手过一个项目,工程师在中断里用disable_irq()处理数据,结果导致PWM输出丢步,电机抖动。中断服务函数应该短平快,需要长时间处理的数据,放到主循环里做。

4.5 中断使能与屏蔽知识体系

下面这张图总结了中断使能与屏蔽的层级关系,我建议你把它记在脑子里:

中断使能与屏蔽层级结构 全局中断使能 PRIMASK / EA 位 外设中断使能 NVIC_ISER / IE 寄存器 事件级中断使能 DIER / 外设使能位 中断屏蔽寄存器 BASEPRI / 屏蔽位 操作顺序建议 ① 配置外设 → ② 使能局部中断 → ③ 设置优先级 ④ 设置BASEPRI(可选)→ ⑤ 开启全局中断 ⑥ 进入主循环 → 中断发生时自动响应

4.6 常见陷阱与避坑指南

  • 中断嵌套失控——我曾经在项目中同时使能了多个同优先级中断,结果它们互相打断,系统响应时间变得不可预测。后来我强制给每个中断分配不同优先级,问题解决。
  • 屏蔽寄存器设置错误——BASEPRI的值是优先级阈值,不是具体中断号。我见过有人把BASEPRI设成0xFF,结果所有中断都被屏蔽了,系统“死机”。
  • 中断使能遗漏——有时候外设配置好了,局部中断也开了,但就是进不了中断。检查一下NVIC里有没有使能该外设的中断通道。这个坑我踩过不止一次。

调试技巧:在中断服务函数入口处翻转一个GPIO引脚,用示波器看这个引脚的波形。如果波形正常,说明中断确实触发了;如果没有波形,说明中断根本没进来,问题在使能配置上。

中断使能与屏蔽,说白了就是一套“谁可以进来”的权限管理。全局中断是总闸,局部中断是分闸,屏蔽寄存器是精细过滤器。把这套机制用好,你的嵌入式系统才能既响应及时,又稳定可靠。