4. 中断机制基础:NVIC嵌套向量中断控制器、中断优先级、中断使能与清除标志位

在嵌入式低功耗串口设计中,中断机制是唤醒CPU、响应异步事件的核心。STM32系列微控制器采用ARM Cortex-M内核的NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)来管理所有中断。理解NVIC的工作原理、优先级配置以及标志位的正确操作,是实现可靠空闲中断唤醒与DMA协同的前提。

4.1 NVIC嵌套向量中断控制器

NVIC是Cortex-M内核内置的中断控制器,负责处理所有外部中断和内部异常。其核心特性包括:

  • 嵌套支持:高优先级中断可以抢占低优先级中断的服务例程,实现优先级嵌套。
  • 向量化中断:每个中断源对应一个固定的中断向量地址,CPU响应中断时自动跳转到对应的服务函数入口。
  • 可编程优先级:支持最多256级优先级(实际芯片会裁剪,如STM32F1系列支持16级)。
  • 尾链技术:当多个中断同时挂起时,NVIC自动跳过出栈/入栈操作,加速中断切换。
低功耗设计要点: 在进入睡眠模式前,必须确保NVIC中对应的唤醒中断(如USART空闲中断)已正确使能,并且优先级配置合理,避免因优先级反转导致唤醒延迟。
NVIC中断处理流程 外设中断源 挂起寄存器 优先级比较 中断向量表 关键寄存器说明: • ISER(中断使能置位寄存器):写1使能对应中断,读返回当前使能状态 • ICER(中断清除使能寄存器):写1禁止对应中断 • ISP(中断挂起置位寄存器):写1强制挂起中断(软件触发) • ICP(中断清除挂起寄存器):写1清除挂起状态

4.2 中断优先级管理

STM32使用4位优先级寄存器(实际有效位数由芯片决定),分为抢占优先级和子优先级两部分。优先级数值越小,优先级越高。

优先级分组 抢占优先级位数 子优先级位数 抢占优先级范围 子优先级范围
NVIC_PriorityGroup_0 0 4 — 0~15
NVIC_PriorityGroup_1 1 3 0~1 0~7
NVIC_PriorityGroup_2 2 2 0~3 0~3
NVIC_PriorityGroup_3 3 1 0~7 0~1
NVIC_PriorityGroup_4 4 0 0~15 —
推荐配置: 在低功耗串口应用中,建议使用 NVIC_PriorityGroup_4(全部为抢占优先级),简化优先级管理。将空闲中断优先级设为较高(数值较小),DMA中断优先级设为较低(数值较大),确保空闲中断能及时唤醒CPU。

4.3 中断使能与清除标志位

正确操作中断使能和标志位清除是避免中断丢失或误触发的关键。以下是标准操作流程:

  1. 配置中断优先级:调用 HAL_NVIC_SetPriority() 设置抢占优先级和子优先级。
  2. 使能中断:调用 HAL_NVIC_EnableIRQ() 将对应中断向量写入ISER寄存器。
  3. 清除挂起位:在使能中断前,先调用 HAL_NVIC_ClearPendingIRQ() 清除可能存在的残留挂起标志。
  4. 中断服务函数中清除标志:进入ISR后,先读取状态寄存器确认中断源,再写入1清除对应标志位。
// 示例:USART空闲中断配置(基于HAL库)
void USART_IdleInterrupt_Config(void)
{
    // 1. 设置中断优先级:抢占优先级1,子优先级0
    HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);

    // 2. 清除可能的残留挂起位
    HAL_NVIC_ClearPendingIRQ(USART1_IRQn);

    // 3. 使能USART1中断
    HAL_NVIC_EnableIRQ(USART1_IRQn);

    // 4. 使能USART空闲中断(在USART_CR1寄存器中)
    USART1->CR1 |= USART_CR1_IDLEIE;
}

// 中断服务函数
void USART1_IRQHandler(void)
{
    // 检查空闲中断标志位
    if (USART1->SR & USART_SR_IDLE)
    {
        // 清除空闲中断标志:先读SR,再读DR
        volatile uint32_t tmp = USART1->SR;
        tmp = USART1->DR;
        (void)tmp;

        // 执行唤醒后的数据处理
        Process_Received_Data();
    }
}
常见陷阱: USART空闲中断标志位的清除方式比较特殊——必须按照“先读状态寄存器SR,再读数据寄存器DR”的顺序操作。如果只读SR而不读DR,标志位无法清除,会导致中断反复触发,CPU无法进入低功耗模式。
中断使能与标志位清除操作流程 1. 配置优先级 2. 清除挂起位 3. 使能中断 4. 使能外设中断 中断触发 → CPU自动入栈 → 查找向量表 → 跳转ISR → 执行服务函数 ISR内部:读取SR确认中断源 清除标志位(读SR+DR或写1) 关键原则: 先清除挂起位再使能中断,避免使能瞬间误触发;ISR中必须清除标志位,否则无法再次进入中断。

4.4 中断优先级在低功耗场景中的设计策略

在空闲中断唤醒与DMA协同的系统中,中断优先级的分配直接影响系统的实时性和功耗表现:

中断源 推荐优先级 设计理由
USART空闲中断 高(如0或1) 需要及时唤醒CPU,避免数据丢失;唤醒延迟直接影响功耗
DMA传输完成中断 中(如2或3) 数据传输完成后通知CPU处理,可容忍短暂延迟
系统滴答定时器 低(如4或5) 用于操作系统心跳或延时,优先级最低,避免干扰唤醒响应
优先级分组一致性: 整个系统必须使用相同的优先级分组(推荐 NVIC_PriorityGroup_4),否则优先级比较结果不可预测。在 HAL_Init() 或系统初始化早期调用 HAL_NVIC_SetPriorityGrouping() 完成配置。