首页/新闻资讯/正文详情

【STM32】 NVIC 与 EXTI 中断 · 超详细源码级解析

发布时间:2026/9/27 6:49:05 来源:云帆数科 栏目:资讯中心
【STM32】 NVIC 与 EXTI 中断 · 超详细源码级解析
NVIC 与 EXTI 中断 · 超详细源码级解析一、AIRCR优先级分组的写保护寄存器1.1 AIRCR 全位图SCB-AIRCR0xE000ED0C位名称说明[31:16]VECTKEYSTAT/VECTKEY写钥匙写入 0x05FA 才允许本次写操作生效读时返回 0xFA05[15]ENDIANNESS端序只读F1 为 0 小端[10:8]PRIGROUP优先级分组3 位决定抢占/子优先级怎么拆[2]SYSRESETREQ写 1 请求系统复位NVIC_SystemReset 用[1]VECTCLRACTIVE清异常活动状态调试用[0]VECTRESET复位内核调试用1.2 为什么必须带 VECTKEY 钥匙AIRCR 是系统级关键寄存器硬件规定bit[31:16] 必须写入 0x05FA否则本次写入整体被忽略。所以 HAL 里所有对 AIRCR 的写操作都长这样SCB-AIRCR 旧值清场 | (新值) | SCB_AIRCR_VECTKEY_Msk;SCB_AIRCR_VECTKEY_Msk (0x05FAUL 16)也就是0x05FA0000。1.3 SetPriorityGrouping 源码逐段再拆void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup)); /* ① 只收合法宏 */ SCB-AIRCR ((SCB-AIRCR ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)) /* ② 清钥匙域分组域保其他位 */ | ((PriorityGroup 0x7UL) SCB_AIRCR_PRIGROUP_Pos) /* ③ 分组宏低3位 → 放到位[10:8] */ | SCB_AIRCR_VECTKEY_Msk); /* ④ 补钥匙 */ }② 是读-改-写先读回 AIRCR把要动的位清零其他位SYSRESETREQ 等原样保留③PriorityGroup 0x7分组宏的低 3 位就是 PRIGROUP 值见下表左移 8 位到 [10:8]④ 最后补钥匙三个操作一次写完。1.4 PRIGROUP 编码与 F1 截断分组宏值PRIGROUP 值宏宏值PRIGROUP(3位)F1 抢占位F1 子优先级位抢占值范围NVIC_PRIORITYGROUP_0711104无全子优先级NVIC_PRIORITYGROUP_16110130~1NVIC_PRIORITYGROUP_25101220~3NVIC_PRIORITYGROUP_34100310~7NVIC_PRIORITYGROUP_43011400~15关键理解PRIGROUP 不改变寄存器里存的 4 位值只改变 NVIC 仲裁时把这 4 位拆成抢占部分子部分的方式。改分组 让所有已配置中断的优先级含义全部重解释。1.5 两个必须知道的点HAL_Init()内部已默认调HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)普通工程不需要再写分组改了HAL_NVIC_SetPriority传参语义跟着变见下节这是坑。二、优先级字节IP/SHP 的位布局核心难点2.1 一个优先级字节长什么样2.2 为什么是 (8 - __NVIC_PRIO_BITS)(PreemptPriority (8U - __NVIC_PRIO_BITS)) | (SubPriority (uint8_t)(0xFFUL __NVIC_PRIO_BITS))F1 的__NVIC_PRIO_BITS 4在stm32f1xx.h里由芯片头文件定义CMSIS 据此生成所有寄存器访问8 - 4 4把 4 位的抢占值左移 4 位放进高 4 位bit7:40xFF 4 0x0F子优先级掩码只允许低 4 位合成一个字节写入 IP/SHP。举例默认 Group4HAL_NVIC_SetPriority(EXTI0_IRQn, 5, 0); /* Preempt5 → 54 0x50Sub0 → IP[6] 0x50 */ /* 硬件读高4位 5 抢占优先级 ✓ */2.3 一个重要事实面试加分点HAL 假设你用 Group4HAL_NVIC_SetPriority的拼接是固定左移 4 位它不会根据当前分组自动重组。这意味着默认 Group4 下Preempt 0~15 直接对应高 4 位Sub 必须传 0完全正确若改成 Group2 想表达抢占 1、子 24 位值应为0b0110但 HAL 写的是(14)|2 0x12硬件取高 4 位 1 → 被拆成抢占 0、子 1子优先级实际不生效。所以实战建议保持 HAL 默认的 Group4只用抢占优先级Sub 一律传 0确实需要子优先级就手动按分组合成一个 4 位值传给 Preempt 参数。2.4 SHP 索引公式推导系统异常那支SCB-SHP[(((uint32_t)(int32_t)IRQn) 0xFUL) - 4UL] ...;负数 IRQn 的补码 0xF 正好等于异常号低 4 位IRQn补码 0xF减 4SHP 索引对应异常号-1 (SysTick)1511SHP[11]15-2 (PendSV)1410SHP[10]14-5 (SVCall)117SHP[7]11-10 (UsageFault)62SHP[2]6-11 (BusFault)51SHP[1]5-12 (MemManage)40SHP[0]4规律SHP 索引 异常号 - 4SHP[0] 对异常 4 开始公式用补码 0xF 巧妙规避了负数运算。2.5 为什么写完要读回/__DSB()NVIC 是慢速外设写操作可能被写缓冲延迟。HAL 在写完优先级后读回一次或部分版本用__DSB()数据同步屏障强制写完成保证紧跟其后的EnableIRQ生效时优先级已就位。否则可能出现中断来了但优先级还是旧的竞态。三、NVIC 全套控制寄存器与周边 API3.1 四个核心寄存器 位映射公式NVIC-ISER[IRQn 5] 1 (IRQn 0x1F); /* 使能 Set-Enable */ NVIC-ICER[IRQn 5] 1 (IRQn 0x1F); /* 禁能 Clear-Enable */ NVIC-ISPR[IRQn 5] 1 (IRQn 0x1F); /* 置挂起 Set-Pending */ NVIC-ICPR[IRQn 5] 1 (IRQn 0x1F); /* 清挂起 Clear-Pending */IRQn 5每组 32 个中断ISER[0] 管 031、ISER[1] 管 32631 (IRQn 0x1F)组内位号。EXTI0_IRQn 6 →ISER[0] (1 6)bit6 置 1。3.2 EXTI 相关中断编号速查F1/F4 通用IRQn编号挂哪个 ISEREXTI0_IRQn6ISER[0] bit6EXTI1_IRQn7ISER[0] bit7EXTI2_IRQn8ISER[0] bit8EXTI3_IRQn9ISER[0] bit9EXTI4_IRQn10ISER[0] bit10EXTI9_5_IRQn23ISER[0] bit23EXTI15_10_IRQn40ISER[1] bit8注意EXTI59 共用 EXTI9_5_IRQHandlerEXTI1015 共用 EXTI15_10_IRQHandler——回调里必须按GPIO_Pin区分是哪条线。3.3 周边 API 源码要点速览API底层动作说明HAL_NVIC_EnableIRQISER 1nHAL_NVIC_DisableIRQICER 1nHAL_NVIC_SetPendingIRQISPR 1nHAL_NVIC_ClearPendingIRQICPR 1nHAL_NVIC_GetPendingIRQ读 ISPR返回是否挂起HAL_NVIC_GetPriority读 IP/SHP 再右移 (8-PRIO_BITS)读回优先级HAL_NVIC_GetPriorityGrouping读 AIRCR PRIGROUP读当前分组HAL_NVIC_SystemResetAIRCR VECTKEY|SYSRESETREQ再死等复位软件复位HAL_NVIC_SystemReset源码void HAL_NVIC_SystemReset(void) { __DSB(); /* 确保之前写完成 */ SCB-AIRCR (uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_SYSRESETREQ_Msk); __DSB(); /* 确保复位请求已发出 */ while (1); /* 等硬件复位 */ }四、HAL_GPIO_Init从时钟到 EXTI 的完整链路4.1 第一步开 GPIO 时钟__HAL_RCC_GPIOA_CLK_ENABLE();F1 展开后本质是SET_BIT(RCC-APB2ENR, RCC_APB2ENR_IOPAEN); /* APB2ENR 的 bit2 GPIOA 时钟门 */忘了开时钟读写 GPIO 寄存器全部无效总线上的寄存器读回 0——这是中断完全不触发的头号原因优先级比 EXTI/NVIC 配置更靠前。4.2 GPIO 寄存器F1 vs F4 差异功能F1CRL/CRH 体系F4MODER 体系方向/模式CRL(07)/CRH(815)CNFMODEMODER2 位/脚速度同上 MODE 位OSPEEDR上下拉同样编码进 CNFPUPDR独立输出类型CNF推挽/开漏OTYPER置位/清零BSRR/BRRBSRR复用AFIO重映射AFRL/AFRHHAL 的GPIO_InitTypeDef是跨系列统一的抽象Pull、Speed、Mode这些字段在 F1 上最终都被编码进 CRL/CRH 的 CNF/MODE 位。4.3 第二步EXTI 源选择这步容易漏EXTI0 只能接 PA0/PB0/PC0/PD0/PE0 中的一根选哪根由源选择寄存器决定F1AFIO-EXTICR[4]CubeMX 生成代码长这样__HAL_RCC_AFIO_CLK_ENABLE(); /* AFIO 也要时钟 */ HAL_GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);HAL_GPIO_EXTILineConfig源码void HAL_GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) { uint32_t tmp 0x00; tmp AFIO-EXTICR[GPIO_PinSource 2]; /* 每 4 根线一组 */ tmp ~(0x0FUL (4 * (GPIO_PinSource 0x03))); /* 清该线旧源 */ tmp | ((uint32_t)GPIO_PortSource (4 * (GPIO_PinSource 0x03))); /* 写新源 */ AFIO-EXTICR[GPIO_PinSource 2] tmp; }F4没有 AFIO改用 SYSCFG且HAL_GPIO_Init内部自动完成__HAL_RCC_SYSCFG_CLK_ENABLE() 写 SYSCFG-EXTICR不需要手动调。只在 PA 上用 EXTI 时EXTICR 默认值 0 PA可以省这一步但 CubeMX 总是生成保留无妨。4.4 第三步HAL_GPIO_Init 的 EXTI 分支源码void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) { /* …… ① GPIO 方向/速度/上下拉/复用配置CRL/CRH 或 MODER 等…… */ if ((GPIO_Init-Mode EXTI_Mode) ! RESET) /* Mode 里带 EXTI 才进 */ { /* ② 上升沿模式含 RISING → RTSR 对应位置 1 */ if ((GPIO_Init-Mode GPIO_MODE_IT_RISING) GPIO_MODE_IT_RISING) SET_BIT(EXTI-RTSR, position); else CLEAR_BIT(EXTI-RTSR, position); /* ③ 下降沿模式含 FALLING → FTSR 对应位置 1 */ if ((GPIO_Init-Mode GPIO_MODE_IT_FALLING) GPIO_MODE_IT_FALLING) SET_BIT(EXTI-FTSR, position); else CLEAR_BIT(EXTI-FTSR, position); /* ④ 中断模式 → 开 IMR 放行事件模式 → 开 EMR不打扰 CPU */ if ((GPIO_Init-Mode GPIO_MODE_IT) GPIO_MODE_IT) SET_BIT(EXTI-IMR, position); else SET_BIT(EXTI-EMR, position); } }到这里外设层就绪边沿选好、IMR 放行。·但 NVIC 没开事件来了只会置 PR 挂起位不会进 ISR。4.5 第四步NVIC 层前文已拆HAL_NVIC_SetPriority(EXTI0_IRQn, 5, 0); /* IP[6] 0x50抢占 5 */ HAL_NVIC_EnableIRQ(EXTI0_IRQn); /* ISER[0] bit6 1 */五、多中断优先级仲裁实战推演5.1 场景配置三个中断抢 CPU/* 默认 Group44 位全抢占数值小紧急 */ HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0); /* 抢占 1按键 */ HAL_NVIC_SetPriority(USART1_IRQn, 2, 0); /* 抢占 2串口 */ HAL_NVIC_SetPriority(SysTick_IRQn, 15, 0); /* 抢占 15HAL_Delay 计时最低 */ HAL_NVIC_EnableIRQ(EXTI0_IRQn); HAL_NVIC_EnableIRQ(USART1_IRQn);5.2 仲裁推演表场景行为结果主循环中按键中断抢占 1 主循环无优先级立即打断主循环进 ISR串口 ISR 中按键来1 2抢占 1 更紧急打断串口 ISR先按键后回来按键 ISR 中串口来2 1抢占 2 不敌 1挂起排队按键处理完再进串口按键串口同时来NVIC 仲裁1 先响应串口挂起随后自动进入SysTick vs 一切外设15 最低永远被外设打断所以 ISR 里 Delay 卡死这就是嵌入式实时性的根基抢占优先级决定谁打断谁同抢占下才轮到子优先级和编号排序。5.3 三层缺一不可检查清单☐ GPIO 时钟开了吗 __HAL_RCC_GPIOx_CLK_ENABLE() ☐ AFIO 时钟开了吗F1 __HAL_RCC_AFIO_CLK_ENABLE() ☐ 边沿选对了吗 RTSR/FTSRHAL_GPIO_Init 的 Mode ☐ EXTI 源选对了吗 AFIO-EXTICR / SYSCFG-EXTICR ☐ IMR 放行了吗 HAL_GPIO_Init 已开 ☐ 优先级写了吗 HAL_NVIC_SetPriority ☐ NVIC 使能了吗 HAL_NVIC_EnableIRQ ☐ 中断函数名对吗 EXTI0_IRQHandler拼错链接到弱默认不触发六、陷阱清单加量版时钟没开GPIO/AFIO 时钟没使能配置全部静默失效中断不触发。改了分组忘了重配Group4→Group2 后所有旧优先级被重新拆位行为全变且 HAL 的 SetPriority 不按分组重组非 Group4 下子优先级形同虚设需手动合成 4 位值传给 Preempt。优先级数值方向搞反0 最大15 最小不是越大越紧急。只开 EXTI 没开 NVICIMR 放行≠中断会响应还差 EnableIRQ。共线 IRQHandler 不判 PinEXTI9_5 / EXTI15_10 共用函数回调里必须if (GPIO_Pin GPIO_PIN_x)。中断函数名拼错EXTI0_IRQHandler写错字母 → 链接到 startup 的弱默认死循环中断像没使能一样。写优先级后立即使能慢速写可能未落地靠读回/__DSB 保证HAL 已内置别自己删。ISR 里调 HAL_Delay / printfSysTick 15 最低抢不进 串口忙等 → 死锁呼应上一章。改 SYSRESETREQ 忘钥匙任何 AIRCR 写操作不带 VECTKEY 都会被忽略。F1 与 F4 寄存器体系混用CRL/CRH vs MODER、AFIO vs SYSCFG移植时对照系列差异表改。

相关推荐

需求文档丢给它,测试点从 60% 提到 90%+
需求文档丢给它,测试点从 60% 提到 90%+

测试人 Skill 全家桶 第①篇开篇我们说了:AI 能写用例,但写不出"该测什么"。 这一篇就上第一个技能:需求拆解 → 测试点。给你完整 SKILL.md、裸问与用 Skill 的真实对比、以及怎么装进你自己的工具。一、先纠正一个误区&#xff… · 2026/9/27 6:48:59

Python数据可视化 Pyecharts 制作 Liquid 水球图
Python数据可视化 Pyecharts 制作 Liquid 水球图

水球图是一种动态的进度展示图表,常用于表示百分比或进度信息。通过水波的高度和波动,用户可以直观地感知数据的变化情况。在pyecharts库中,Liquid类为生成水球图提供了强大的功能支持,允许用户通过多种选项自定义水球的形状、颜色、动画等特性。无论是单一数据点的展示,还… · 2026/9/27 6:48:53

strands-agents Python SDK v0.1.5 技术解析:动态 System Prompt 覆盖、推理文本回调与滑动窗口上下文管理的实战演进
strands-agents Python SDK v0.1.5 技术解析:动态 System Prompt 覆盖、推理文本回调与滑动窗口上下文管理的实战演进

人工智能大模型AI AgentAgent 框架多智能体工具调用MCP 服务 【免费下载链接】harness-sdk Build an agent harness and control it end-to-end. Open-source SDK for production AI agents in Python & TypeScript - any model, any cloud. 项目地址: https://… · 2026/9/27 6:48:53

镜面检测(Mirror Detection)介绍
镜面检测(Mirror Detection)介绍

文章目录一、镜面检测介绍二、术语表 glossary三、镜面检测模型1.通用型语义分割 / 边缘检测模型:EGNet、MINet、LDF、VST2.经典语义分割骨干网络:PSPNet、DANet、UperNet3.显著目标检测 (Salient Object Detection, SOD)4.玻璃检测 (glass detection)5.… · 2026/9/27 7:31:40

kube-prometheus 监控附加命名空间:通过 jsonnet 扩展 Prometheus 抓取范围与 ServiceMonitor 实战指南
kube-prometheus 监控附加命名空间:通过 jsonnet 扩展 Prometheus 抓取范围与 ServiceMonitor 实战指南

云原生可观测性指标监控监控大盘告警 【免费下载链接】kube-prometheus Use Prometheus to monitor Kubernetes and applications running on Kubernetes 项目地址: https://gitcode.com/gh_mirrors/ku/kube-prometheus 点击查看 免费下载 导读 在默认部署中&… · 2026/9/27 7:31:40

Longhorn 定时快照清理:snapshot-delete 与 snapshot-cleanup 任务类型实战指南
Longhorn 定时快照清理:snapshot-delete 与 snapshot-cleanup 任务类型实战指南

云原生存储高可用容器编排 【免费下载链接】longhorn Cloud-Native distributed storage built on and for Kubernetes 项目地址: https://gitcode.com/gh_mirrors/lo/longhorn 点击查看 免费下载 导读 Longhorn 的 RecurringJob(定时任务)… · 2026/9/27 7:31:40

Linux系统管理工具supervisor使用详解!
Linux系统管理工具supervisor使用详解!

supervisor是一个进程管理工具,当进程中断的时候supervisor能自动重新启动它,同时,它也是一个客户端/服务器系统,允许用户在类unix操作系统上控制多个进程。supervisor是用Python开发的一套通用的进程管理程序,能将一个… · 2026/9/27 7:31:34

MySQL复杂查询与Union操作
MySQL复杂查询与Union操作

在日常开发中,数据查询是数据库操作的核心部分,尤其是在处理多表数据时,单一的查询方式无法满足业务的复杂需求。因此,掌握复杂查询技术变得至关重要。 本教程将介绍如何使用UNION操作进行多表数据合并查询,并通过CASE语句实现条件选择。通过对这些技巧的学习,可以轻松处… · 2026/9/27 7:31:34

用代码设计你自己的机器人:Build123d、Text-to-CAD 与 ForgeCAD 参数化建模入门指南
用代码设计你自己的机器人:Build123d、Text-to-CAD 与 ForgeCAD 参数化建模入门指南

用代码设计你自己的机器人:Build123d、Text-to-CAD 与 ForgeCAD 参数化建模入门指南 【免费下载链接】every-embodied 仅需Python基础,从0构建自己的具身智能机器人;从0逐步构建VLA/OpenVLA/SmolVLA/Pi0, 深入理解具身智能 项目… · 2026/9/27 7:31:28

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码