stm32f103学习笔记-17-STM32 中断应用总结

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 比较顺序(总结)

当多个中断同时发生时,比较顺序为:

  1. 比较主优先级:主优先级高的先执行(可嵌套)。

  2. 如果主优先级相同,比较子优先级:子优先级高的先执行。

  3. 如果子优先级也相同,比较硬件中断编号:编号小的先执行(编号见向量表)。

5. 中断编程的四个必备步骤(实战流程)

配置中断的通用步骤包括:

  1. 使能中断请求:在外设中开启中断功能。

  2. 配置优先级分组:设置全局优先级分组方式(通常只调用一次)。

  3. 配置NVIC寄存器:设置中断通道、优先级和使能。(参考misc.h)

  4. 编写中断服务函数(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函数名必须与向量表一致,且要清除中断标志。

  • 常见错误:函数名错误、未清除标志、优先级配置不当。

  • 调试时使用调试器和日志输出,快速定位问题。

相关推荐
伯明翰java2 小时前
Redis学习笔记-List列表(2)
redis·笔记·学习
云帆小二2 小时前
从开发语言出发如何选择学习考试系统
开发语言·学习
Elias不吃糖2 小时前
总结我的小项目里现在用到的Redis
c++·redis·学习
就是蠢啊2 小时前
51单片机——数码管
单片机·嵌入式硬件·51单片机
别掩3 小时前
三极管恒流电路
单片机·嵌入式硬件
BullSmall3 小时前
《道德经》第六十三章
学习
花落已飘3 小时前
STM32 SDIO接口介绍
stm32·单片机·嵌入式硬件
AA陈超3 小时前
使用UnrealEngine引擎,实现鼠标点击移动
c++·笔记·学习·ue5·虚幻引擎
BullSmall3 小时前
《道德经》第六十二章
学习
Knox_Lai4 小时前
数据结构与算法学习(0)-常见数据结构和算法
c语言·数据结构·学习·算法