当前位置: 首页 > news >正文

中断机制及NVIC管理解析

1. 什么是中断?

中断(Interrupt) 是一种计算机系统中的重要机制,允许CPU在执行主程序的过程中,能够对外部或内部的特定事件作出快速响应。当中断发生时,CPU暂停当前的任务,转而执行对应的中断服务函数(ISR, Interrupt Service Routine),处理完毕后再恢复到原任务继续执行。

中断的作用是提高系统的响应速度和实时性,避免采用轮询(Polling)方式带来的CPU资源浪费。


2. 中断执行机制

中断的执行流程如下:

  1. 中断事件发生:可能来自外部设备(如串口、定时器、GPIO 触发)或内部异常(如除零错误)。
  2. NVIC(Nested Vectored Interrupt Controller)检测:NVIC 负责管理 Cortex-M4 的中断控制,包括优先级排序和嵌套处理。
  3. CPU 保存上下文:CPU 保留当前指令地址(PC)、状态寄存器(xPSR)及相关寄存器。
  4. 跳转到中断向量表(Vector Table):根据中断编号,跳转至相应的 ISR 处理函数。
  5. 执行 ISR:处理中断源的相关逻辑,如清除标志位、读取数据等。
  6. 恢复上下文:恢复寄存器数据,继续执行原来的主程序。

3. 普通函数执行与中断服务函数执行的区别

普通函数中断服务函数
通过函数调用执行由硬件或软件事件触发
需要手动调用由 CPU 自动调用
运行在主程序上下文运行在中断上下文
可以有返回值不能有返回值
可使用 while(1) 等循环需尽快执行完毕,避免阻塞主程序

中断函数必须尽量精简,避免占用 CPU 过多时间,否则会影响系统的实时性。


4. NVIC(中断管理控制器)

Cortex-M4 内核的 NVIC(Nested Vectored Interrupt Controller) 负责管理所有外部和内部中断,包括中断的使能、优先级管理以及嵌套控制

在 STM32F4 系列中,NVIC 相关寄存器如下:

  1. NVIC_ISERx(中断使能寄存器)
  2. NVIC_ICERx(中断清除寄存器)
  3. NVIC_ISPRx(中断挂起寄存器)
  4. NVIC_ICPRx(中断清除挂起寄存器)
  5. NVIC_IABRx(中断活动状态寄存器)
  6. NVIC_IPRx(中断优先级寄存器)

示例:使能 USART2 中断并配置优先级

c

复制

#define USART2_IRQn  38   // USART2 中断号

void NVIC_Configuration(void)
{
    NVIC->ISER[USART2_IRQn / 32] = (1 << (USART2_IRQn % 32));  // 使能 USART2 中断
    NVIC->IP[USART2_IRQn] = (3 << 4);  // 设置优先级为3(较低)
}

5. 什么时候使用中断?

一般情况下,我们会在以下场景使用中断:

  1. 被动事件触发(不适合轮询方式)

    • 串口数据接收(UART RX)
    • 外部按键按下(GPIO 外部中断)
    • 传感器数据更新(I2C/SPI)
  2. 系统定时控制

    • 定时器溢出中断(Timer Overflow)
    • 任务切换(RTOS SysTick)
  3. 高优先级任务

    • 硬件异常(HardFault, BusFault)
    • DMA 传输完成(DMA Transfer Complete)

示例:配置 GPIO 外部中断

c

复制

void EXTI15_10_IRQHandler(void)
{
    if (EXTI->PR & (1 << 13)) // 读取中断挂起标志位
    {
        EXTI->PR = (1 << 13); // 清除标志位
        GPIOB->ODR ^= (1 << 0); // 切换 LED 状态
    }
}

6. 中断优先级

6.1 优先级比较

Cortex-M4 中断优先级分为抢占优先级(Preemptive Priority)响应优先级(Sub Priority)

  • 抢占优先级:决定是否能打断当前正在执行的中断
  • 响应优先级:决定多个相同抢占优先级的中断在同时到达时的处理顺序

优先级越小,优先级越高。例如:

  • 抢占优先级 0 > 1 > 2
  • 响应优先级 0 > 1 > 2(在相同抢占优先级下)

6.2 优先级分组计算公式

STM32F4 允许我们通过 AIRCR(Application Interrupt and Reset Control Register) 配置优先级分组,计算公式如下:

复制

优先级分组编码值 = 7 - 抢占优先级位数

示例:

  • NVIC_PriorityGroup_0(7-0=7):全部 4 位用于响应优先级
  • NVIC_PriorityGroup_4(7-4=3):4 位用于抢占优先级,仅 0 位用于响应优先级

配置代码:

c

复制

void NVIC_SetPriorityGrouping(uint32_t priority_group)
{
    SCB->AIRCR = (0x5FA << 16) | (priority_group << 8); // 设置优先级分组
}

7. 中断的具体配置

7.1 分组

c

复制

NVIC_SetPriorityGrouping(3);  // 选择合适的优先级分组

7.2 配置具体中断源

c

复制

NVIC_SetPriority(USART2_IRQn, 2, 1);  // 设置 USART2 中断的优先级

7.3 使能 NVIC

c

复制

NVIC_EnableIRQ(USART2_IRQn);  // 使能 USART2 中断

8. 中断服务函数(ISR)

8.1 ISR 的特点

  • 无返回值 (void)
  • 函数名固定,需符合 IRQHandler 格式
  • 尽量简短,避免执行耗时操作

8.2 ISR 格式

c

复制

void USART2_IRQHandler(void)
{
    if (USART2->SR & USART_SR_RXNE)  // 判断 RXNE 标志位(接收非空)
    {
        char data = USART2->DR;  // 读取数据
        USART2->DR = data;  // 回显
    }
}

9. 总结

  • 中断是 CPU 处理异步事件的关键机制,适用于被动触发的事件。
  • NVIC 提供了中断管理功能,包括优先级控制和中断使能。
  • STM32F4 允许我们配置抢占优先级和响应优先级,根据应用需求设定分组。
  • ISR 需要尽量短小高效,避免影响系统性能

通过合理配置中断,可以让系统更加高效、实时响应外部事件。

相关文章:

  • Xavier 初始化:深度网络权重初始化的经典之作
  • Java小白-管理项目工具Maven(2)初识Maven
  • Cursor配置Golang开发环境
  • Java变量与常量
  • ubuntu 22.04 本地部署DeepSeek的Janus Pro
  • BigFoot EventAlertMod lua
  • 【hot100】046全排列
  • 初识数组下篇
  • 滑动窗口及边缘化直观理解
  • Maven 的常用指令
  • 编程视界:C++命名空间
  • 人工智能之数学基础:坐标变换
  • 【JavaEE】SpringIoC与SpringDI
  • 详细学习 pandas 和 xlrd:从零开始
  • 软件设计模式之简单工厂模式
  • PHP将HTML标签转化为图片
  • 理解字符流和字节流,节点流和处理流、缓冲流、InputStreamReader、BufferInputStream、BufferReader...
  • 深入解析 C 语言中含数组和指针的构造体与共同体内存计算
  • 在python中运行Wireshark抓包并保存
  • 【MACOS】用户数据过多
  • 苏东坡:人生就是哈哈哈哈哈
  • 国家统计局:4月份居民消费价格同比下降0.1%
  • 巴基斯坦称成功拦截印度导弹,空军所有资产安全
  • 人民财评:网售“婴儿高跟鞋”?不能让畸形审美侵蚀孩子身心
  • “爱鸟周”为何不能像FI和花展那样“市区联动”
  • 警惕“全网最低价”等宣传,市监总局和中消协发布直播消费提示