1. 为什么要理解中断(概念速览)
中断是STM32微控制器中的核心机制,允许处理器在正常程序执行过程中响应内部或外部事件(如按键按下、数据接收完成),临时打断当前任务,转去执行特定的中断服务程序(ISR),执行完毕后再返回原程序继续执行。理解中断对于实现实时处理、多任务协调和高效资源利用至关重要。在STM32中,"中断"和"异常"是同一概念,可互换使用。
中断的执行流程类似于"打断-处理-返回":
-
正常程序执行:程序顺序执行,如时间轴从左到右。
-
中断发生:事件触发(如串口接收数据),处理器暂停当前程序,保存现场(如程序计数器值)。
-
执行ISR:跳转到对应的中断服务函数执行处理逻辑。
-
返回恢复:ISR执行完毕后,恢复现场,继续执行主程序。
STM32支持中断嵌套:高优先级的中断可以打断低优先级的中断。例如,如果正在执行优先级2的ISR,此时发生优先级1的中断(数字越小优先级越高),则优先级1的ISR会立即执行,完成后才返回优先级2的ISR。
2. 中断的分类(二大类)
STM32中断分为两大类,通过中断向量表管理(参考《STM32F10x-中文参考手册》第九章"中断和事件"):
-
系统异常:由内核本身触发,共10个。例如:
-
复位中断(Reset):优先级最高,芯片复位时触发。
-
系统滴答定时器中断(SysTick):用于操作系统时基。
-
硬件错误中断(HardFault):如内存访问错误。
-
非屏蔽中断(NMI):不可被屏蔽,用于紧急事件。
-
-
外部中断:由外设触发,共60个。例如:
-
GPIO引脚变化中断(通过EXTI线):如按键按下。
-
串口(USART)发送/接收完成中断。
-
定时器(TIM)溢出或捕获中断。
-
ADC转换完成中断。
-
中断向量表列出了所有中断的编号和优先级,查阅参考手册可获取完整列表。系统异常编号为负(如-1 to -15),外部中断编号为正(0 to 59)。
3. NVIC(Nested Vectored Interrupt Controller)
NVIC(嵌套向量中断控制器)是Cortex-M3内核的外设,统一管理所有中断,就像"中断管理员"。其主要功能包括:
-
中断使能控制:每个中断都有一个开关,通过NVIC寄存器开启或关闭。
-
优先级管理:设置中断的优先级,决定处理顺序。
-
中断响应:当多个中断同时发生时,根据优先级调度。
在编程中,我们通常使用库函数(如NVIC_Init())来配置NVIC,而不是直接操作寄存器,以简化代码。NVIC的寄存器包括:
-
ISER(中断使能寄存器):用于使能中断。
-
ICER(中断清除寄存器):用于禁用中断。
-
IPR(中断优先级寄存器):设置优先级。
NVIC通过数组结构管理中断:每32个中断使用一个32位寄存器(如ISER[0]控制中断0-31,ISER[1]控制中断32-63等)。
4. 中断优先级(核心、最容易弄错)
4.1 概念
中断优先级决定了中断的执行顺序。STM32使用8位优先级寄存器,但实际只使用高4位(Bit7~Bit4),因此优先级值范围是0~15(数值越小优先级越高)。优先级分为两种:
-
主优先级(抢占优先级):高主优先级的中断可以打断低主优先级的中断(实现嵌套)。
-
子优先级:当两个中断的主优先级相同时,子优先级高的先执行;如果子优先级也相同,则比较硬件中断编号(编号小的优先)。
4.2 位宽与分组(PRIGROUP)

优先级通过"分组"配置,由SCB(系统控制块)的AIRCR寄存器中的PRIGROUP字段控制。STM32有5种分组方式,决定主优先级和子优先级各占多少位:
| 分组编号 | 主优先级位数 | 子优先级位数 | 描述 |
|---|---|---|---|
| 0 | 0位 | 4位 | 无抢占,只有子优先级 |
| 1 | 1位 | 3位 | 主优先级范围0-1,子优先级0-7 |
| 2 | 2位 | 2位 | 主优先级范围0-3,子优先级0-3 |
| 3 | 3位 | 1位 | 主优先级范围0-7,子优先级0-1 |
| 4 | 4位 | 0位 | 完全抢占,主优先级范围0-15 |
常用库函数NVIC_PriorityGroupConfig()进行分组设置,例如:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 使用分组2:主优先级2位,子优先级2位
4.3 比较顺序(总结)
当多个中断同时发生时,比较顺序为:
-
比较主优先级:主优先级高的先执行(可嵌套)。
-
如果主优先级相同,比较子优先级:子优先级高的先执行。
-
如果子优先级也相同,比较硬件中断编号:编号小的先执行(编号见向量表)。
5. 中断编程的四个必备步骤(实战流程)
配置中断的通用步骤包括:
-
使能中断请求:在外设中开启中断功能。
-
配置优先级分组:设置全局优先级分组方式(通常只调用一次)。
-
配置NVIC寄存器:设置中断通道、优先级和使能。(参考misc.h)
-
编写中断服务函数(ISR):实现中断处理逻辑,并清除中断标志。
示例:配置USART1接收中断
// 步骤1: 使能外设中断(USART1接收中断)
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 允许USART1接收中断
// 步骤2: 配置优先级分组(系统一次性设置)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 使用分组2
// 步骤3: 配置NVIC(嵌套向量中断控制器)
// NVIC是Cortex-M3内核的中断管理器,负责中断优先级处理和使能控制
NVIC_InitTypeDef NVIC_InitStructure; // 初始化NVIC配置结构体
// 设置中断通道:指定要配置的中断源(如USART1_IRQn),完整列表参考stm32f10x.h中的IRQn_Type枚举
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // 中断通道:选择USART1中断
// 设置抢占优先级(主优先级):值范围0-15(具体取决于优先级分组),数值越小优先级越高,允许高优先级中断嵌套
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级:设置为1,可被更高优先级中断嵌套
// 设置子优先级:值范围0-15,当抢占优先级相同时,子优先级高的先执行;若都相同,按硬件中断编号决定
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级:设置为1,用于同优先级时的执行顺序
// 使能中断通道:控制中断是否生效,ENABLE表示开启中断响应,DISABLE则禁用
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断:开启USART1中断响应
// 应用NVIC配置:将参数写入NVIC寄存器,完成中断设置
NVIC_Init(&NVIC_InitStructure); // 初始化NVIC,激活配置
// 步骤4: 编写ISR(函数名必须精确)
void USART1_IRQHandler(void) {
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
uint8_t ch = USART_ReceiveData(USART1); // 读取接收数据
// 处理数据(如存入缓冲区),尽量保持简短
USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 清除中断标志
}
}
6. 向量表与ISR命名(常犯错点)
中断向量表是存储在Flash起始地址的一张表,包含了所有中断服务函数的入口地址。启动文件(如startup_stm32f10x.s)中预定义了每个中断的默认ISR名称。编写ISR时,函数名必须与向量表中的名称完全一致,否则编译器不会报错,但程序可能进入默认错误处理循环(如无限循环)。
常见ISR命名示例:
-
EXTI0_IRQHandler:用于EXTI线0中断。 -
USART1_IRQHandler:用于USART1中断。 -
SysTick_Handler:用于系统滴答定时器中断。
所有ISR应集中 在**stm32f10x_it.c** 文件中,便于管理。
7. 常见错误与调试建议(实践经验)
-
错误1:ISR函数名拼写错误:导致中断无法正确触发,程序进入默认Handler。解决方案:检查启动文件中的函数名,确保一致。
-
错误2:未清除中断标志 :中断持续触发,系统卡死。解决方案:在ISR末尾调用清除标志函数(如
EXTI_ClearITPendingBit())。 -
错误3:优先级配置错误:中断嵌套行为不符合预期。解决方案:合理设置优先级分组和优先级值。
-
错误4:ISR执行时间过长:影响系统实时性。解决方案:ISR应尽量简短,仅处理关键操作,将耗时任务放在主循环中(通过标志位触发)。
-
错误5:未使能全局中断 :有时需要确保全局中断使能(
__enable_irq()),但通常库函数已处理。
调试建议:
-
使用调试器(如JTAG)设置断点,观察中断是否触发。
-
检查NVIC和外设寄存器值,确认中断使能和优先级设置正确。
-
添加日志输出(通过串口),跟踪中断执行情况。
8. 调试技巧(快速定位问题)
-
查看向量表:确认ISR地址是否正确映射。
-
使用ST-Link或其他调试器:单步执行ISR,观察变量和寄存器。
-
模拟中断:通过软件触发中断(如设置NVIC->STIR寄存器)测试ISR逻辑。
-
检查时钟配置 :确保外设时钟已使能(如通过
RCC_APB2PeriphClockCmd())。 -
利用错误处理函数 :如
HardFault_Handler,可添加调试代码捕获意外错误。
10. 总结(要点回顾)
-
中断是STM32实现实时处理的核心机制,分为系统异常和外部中断。
-
NVIC统一管理所有中断,包括使能、优先级设置和响应。
-
优先级分主优先级(抢占)和子优先级,通过分组配置(5种方式)。
-
编程步骤:使能外设中断→设置优先级分组→配置NVIC→编写ISR。
-
ISR函数名必须与向量表一致,且要清除中断标志。
-
常见错误:函数名错误、未清除标志、优先级配置不当。
-
调试时使用调试器和日志输出,快速定位问题。