【STM32】中断与NVIC以外部中断为例
前言
在stm32中姑且可以认为,异常就是中断
单片机上电之后,首先执行启动文件,开辟堆栈之后,开始初始化中断向量表。
NVIC
NVIC
NVIC是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。
####三个寄存器ISER、ICER 和IP
NVIC 结构体定义,来自固件库头文件:core_cm3.h
在配置中断的时候我们一般只用 ISER、ICER 和IP 这三个寄存器,ISER 用来使能中断,ICER 用来失能中断,IP 用来设置中断优先级。

ISER[8]:Interrupt Set Enable Registers,这是一个中断使能寄存器组。是个u32类型的数组,成员有8个。 CM3、4 内核支持 256 个中断,这里用 8 个 32 位寄存器来控制,每个位控制一个中断。根据单片机生产厂商的设计,不一定会全部使用到。
ICER[8]:全称是:Interrupt Clear Enable Registers,是一个中断除能寄存器组。该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。其对应位的功能,也和 ISER 一样。这里要专门设置一个 ICER 来清除中断位,而不是向 ISER 写 0 来清除,是因为 NVIC 的这些寄存器都是写 1 有效的,写 0 是无效的。
IP [240]:全称是:Interrupt Priority Registers,是一个中断优先级控制的寄存器组。这个寄存器组相当重要!STM32F407 的中断分组与这个寄存器组密切相关。IP 寄存器组由 240 个 8bit的寄存器组成,每个可屏蔽中断占用 8bit,这样总共可以表示 240 个可屏蔽中断。而 STM32F407只用到了其中的 82 个。IP[81]-IP[0]分别对应中断 81~0。而每个可屏蔽中断占用的 8bit 并没有
全部使用,而是只用了高 4 位。这 4 位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。而这两个优先级各占几个位又要根据 SCB->AIRCR 中的中断分组设置来决定。
//----------以上是常用的NVIC寄存器,对NVIC的配置实际上就是配置这几个寄存器----------//
ISPR[8]:全称是:Interrupt Set Pending Registers,是一个中断使能挂起控制寄存器组。每个位对应的中断和 ISER 是一样的。通过置 1,可以将正在进行的中断挂起,而执行同级或更高级别的中断。写 0 是无效的。
ICPR[8]:全称是:Interrupt Clear Pending Registers,是一个中断解挂控制寄存器组。其作用与 ISPR 相反,对应位也和 ISER 是一样的。通过设置 1,可以将挂起的中断解挂。写 0 无效。
IABR[8]:全称是:Interrupt Active Bit Registers,是一个中断激活标志位寄存器组。对应位所代表的中断和 ISER 一样,如果为 1,则表示该位所对应的中断正在被执行。这是一个只读寄存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。
优先级的定义
1.优先级只有主优先级和子优先级
2.所谓的优先级分组是决定了IP寄存器的高4bit,其中哪几位代表主优先级,几位代表子优先级
3.数值越小所代表的优先级就越高
4.抢占优先级:抢占优先级高的中断可以打断正在执行的抢占优先级低的中断。
5.响应优先级:抢占优先级相同,响应优先级高的中断不能打断响应优先级低的中断。
还有一种情况就是当两个或者多个中断的抢占式优先级和响应优先级相同时,那么就遵循
自然优先级,看中断向量表的中断排序,数值越小,优先级越高。
先比较主优先级,再比较sub优先级,再按中断向量表的优先级序号比较

中断优先级寄存器 NVIC_IPRx,用来配置外部中断的优先级,IPR 宽度为 8bit,原则上每个外部中断可配置的优先级为 0~255,数值越小,优先级越高。但是绝大多数CM3芯片都会精简设计,以致实际上支持的优先级数减少,在F103中,只使用了高 4bit。而这高4bit也会根据CB->AIRCR 寄存器的 bit10~8 的配置来决定主优先级占几位,子优先级占几位。

优先级的分组由内核外设 SCB 的应用程序中断及复位控制寄存器 AIRCR 的PRIGROUP[10:8]位决定,也就是说用于表达优先级的这4bit还需要根据优先级分组的配置,再进行主优先级和子优先级的配置。
优先级分组的设置是由 SCB->AIRCR 寄存器的 bit10~8 来定义的.

举个例子_设置优先级
设置优先级:设置优先级分组之后,再设置主优先级和子优先级
1.设置优先级分组
2.设置主优先级
3.设置sub优先级
例如SCB->AIRCR 寄存器的 bit10~8将优先级分组设置为3,那么此时所有的 82 个中断,每个中断的中断优先寄存器的高四位中的最高 3 位是抢占优先级,低 1 位是响应优先级。每个中断,你可以设置抢占优先级为 0~7,响应优先级为 1 或 0。抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。
举个例子_中断的打断
抢占优先级:抢占优先级高的中断可以打断正在执行的抢占优先级低的中断。
响应优先级:抢占优先级相同,响应优先级高的中断不能打断响应优先级低的中断。
假定设置中断优先级分组为 2,然后设置中断 3(RTC_WKUP 中断)的抢占优先级为 2,响应优先级为 1。中断 6(外部中断 0)的抢占优先级为 3,响应优先级为 0。中断 7(外部中断 1)的抢占优先级为 2,响应优先级为 0。那么这 3 个中断的优先级顺序为:
中断 7>中断 3>中断 6。
上面例子中的中断 3 和中断 7 都可以打断中断 6 的中断。而中断 7 和中断 3 却不可以相互打断!
NVIC 中断相关的库函数都在库文件 misc.c 和 misc.h 中
中断编程要点
一般情况下不使用库函数封装好的函数
编程时主要进行三步
1.使能中断
使能外设某个中断,比如USART的传输完成中断,接受完成中断等,这些由相关外设的控制寄存器进行控制,配置控制寄存器进行使能。这边是允许外设的具体某个中断,还需要在NVIC操作 NVIC_ISER 和 NVIC_ICER 这两个寄存器,进行中断的使能
2.配置NVIC
初始化 NVIC_InitTypeDef 结构体

2.1 设置中断源


2.2设定主优先级和sub优先级
2.3中断使能(ENABLE)或者失能(DISABLE),操作的是 NVIC_ISER 和 NVIC_ICER 这两个寄存器。
3.编写中断服务函数
启动文件 startup_stm32f10x_hd.s 中预先定义了中断服务函数,可以在里面进行编写。
NVIC 相关函数
NVIC 中断相关的库函数都在库文件 misc.c 和 misc.h 中(stm32f1系列)
把 core_cm4.h 文件的 NVIC 相关函数封装到 stm32f4xx_hal_cortex.c 文件中(stm32f4系列)
以外部中断EXTI为例
代码差不多就是这个意思,具体使用时需要修改
配置GPIO PA0引脚作为外部中断的流程
1) 使能 IO 口时钟。
使用 GPIO 之前必须开启 GPIO 端口的时钟;用到 EXTI 必须开启 AFIO 时钟。
GPIO_InitTypeDef GPIO_InitStructure;//
EXTI_InitTypeDef EXTI_InitStructure;//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);//打开GPIO的时钟,打开AFIO的时钟,
2)配置中断优先级(NVIC)
NVIC_InitTypeDef NVIC_InitStructure;
/* 配置 NVIC 为优先级组 1 所有82个中断源都属于优先级组1,主优先级0-1,子优先级0-7*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);/* 配置中断源:exti1 */
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;/* 配置抢占优先级:1 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;/* 配置子优先级:1 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;/* 使能中断通道 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
3) 设置 IO 口模式,触发条件,设置 IO 口与中断线的映射关系,并使能中断。
# 设定GPIO模式
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;#浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);#设定EXTI触发条件
/* 选择 EXTI 的信号源 */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);EXTI_InitStructure.EXTI_Line = EXTI_Line0;
/* EXTI 为中断模式 */
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
/* 上升沿中断 */
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
/* 使能中断 */
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
4) 编写中断服务函数。
void EXTI0_IRQHandler(void){//确保是否产生了 EXTI Line 中断if (EXTI_GetITStatus(EXTI_Line0) != RESET){//TodoEXTI_ClearITPendingBit(EXTI_Line0);}
}相关文章:
【STM32】中断与NVIC以外部中断为例
前言 在stm32中姑且可以认为,异常就是中断 单片机上电之后,首先执行启动文件,开辟堆栈之后,开始初始化中断向量表。 NVIC NVIC NVIC是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦…...
大学生网页设计制作作业实例代码 (全网最全,建议收藏) HTML+CSS+JS
文章目录 📚web前端期末大作业 (1500套) 集合一、网页介绍二、网页集合 三、作品演示A电影主题B漫画主题C商城主题D家乡主题E旅游主题F餐饮/美食主题G环境主题H游戏主题I 个人主题K体育主题L博客主题M汽车主题N文化主题P美妆主题Q企业主题R教育主题S其他主题 &#…...
Llama模型结构解析(源码阅读)
目录 1. LlamaModel整体结构流程图2. LlamaRMSNorm3. LlamaMLP4. LlamaRotaryEmbedding 参考资料: https://zhuanlan.zhihu.com/p/636784644 https://spaces.ac.cn/archives/8265 ——《Transformer升级之路:2、博采众长的旋转式位置编码》 前言&#x…...
基于XML实现SpringIoC配置
目录 SpringIoc创建与使用的大致步骤 一.基于xml配置SpringIoc 二.基于xml配置DI 三.创建IoC容器并获取组件 SpringIoc创建与使用的大致步骤 SpringIoC的创建与使用过程分为3步 1.编写配置信息(编写XML,注解、Java类) 2.创建IoC容器&…...
Kaniko在containerd中无特权快速构建并推送容器镜像
目录 一、kaniko是什么 二、kaniko工作原理 三、kanijo工作在Containerd上 基于serverless的考虑,我们选择了kaniko作为镜像打包工具,它是google提供了一种不需要特权就可以构建的docker镜像构建工具。 一、kaniko是什么 kaniko 是一种在容器或 Kube…...
分享5款不会被打入冷宫的神器软件
检查一下你最近安装的软件,他们是不是都一样无法避免最终被你打入冷宫的命运?我们明明很懂“在精不在多”的道理,却依然让我们的电脑塞满了形形色色无用的软件。你需要知道的是,如何找到一款适合自己且真正实用的电脑软件。 自…...
Windows如何部署Redis
一、简介 Redis (Remote Dictionary Server) 是一个由意大利人 Salvatore Sanfilippo 开发的 key-value 存储系统,具有极高的读写性能,读的速度可达 110000 次/s,写的速度可达 81000 次/s 。 二、下载 访问 https://github.com/tporadows…...
VUE数据双向绑定原理解析
VUE数据双向绑定原理解析 在Vue.js中,数据双向绑定是一项非常强大的功能。它使开发者能够轻松地将模板与数据进行动态关联,实现了页面和数据之间的实时同步更新。本文将深入探讨VUE中数据双向绑定的原理,并通过代码示例演示其工作机制。 1.…...
SSM商城项目实战:订单管理
SSM商城项目实战:订单管理 在SSM商城项目中,订单管理是一个非常重要的功能模块。本文将详细介绍订单管理的实现思路和步骤代码。 实现SSM商城项目中订单管理功能的思路如下: 设计数据库表结构:根据订单管理的需求,设计…...
SELinux 入门 pt.2
哈喽大家好,我是咸鱼 在《SELinux 入门 pt.1》中,咸鱼向各位小伙伴介绍了 SELinux 所使用的 MAC 模型、以及几个重要的概念(主体、目标、策略、安全上下文) 我们还讲到: 对于受 SELinux 管制的进程,会先…...
函数(个人学习笔记黑马学习)
1、函数定义 #include <iostream> using namespace std;int add(int num1, int num2) {int sum num1 num2;return sum; }int main() {system("pause");return 0; } 2、函数的调用 #include <iostream> using namespace std;int add(int num1, int num2…...
《Flink学习笔记》——第五章 DataStream API
一个Flink程序,其实就是对DataStream的各种转换,代码基本可以由以下几部分构成: 获取执行环境读取数据源定义对DataStream的转换操作输出触发程序执行 获取执行环境和触发程序执行都属于对执行环境的操作,那么其构成可以用下图表示…...
Vue3.0 新特性以及使用变更总结
Vue3.0 在2020年9月正式发布了,也有许多小伙伴都热情的拥抱Vue3.0。去年年底我们新项目使用Vue3.0来开发,这篇文章就是在使用后的一个总结, 包含Vue3新特性的使用以及一些用法上的变更。 图片.png 为什么要升级Vue3 使用Vue2.x的小伙伴都熟悉…...
ToBeWritten之VSOC安全运营
也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 转移发布平台通知:将不再在CSDN博客发布新文章,敬…...
2023爱分析·一站式通信解决方案市场厂商评估报告:牛信云
[图片] 01 中国企业出海发展背景及阶段 出海背景:出海,对中国企业而言,并不陌生。从最初的贸易型出海,到制造业崛起,再到互联网、移动互联网产业腾飞,中国企业在出海道路上走的越发稳健。行业也从最初的家电…...
微信小程序消防知识每天学平台设计与实现
摘 要 消防是当下一个人都需要在日常生活中所高度重视的事项。消防安全关系到居民的日常生活的安全,通过学习消防知识能够提升人们在日常生活中对于灾难的防范。通过对当下的大学生进行调查研究后发现,现在的年轻人在消防意识上比较的单薄,对…...
Oracle跨库访问DBLINK
1. DBLINK的介绍 Oracle在进行跨库访问时,可以创建DBLINK实现,比如要将UAT的表数据灌入开发环境,则可以使用UAT库为数据源,通过DBLINK实现将查出的数据灌入开发库。 简而言之就是在当前数据库中访问另一个数据库中的表中的数据 2…...
【vue3.0 组合式API与选项式API是什么,有什么区别】
vue3.0 组合式API与选项式API是什么 Vue3.0中引入了组合式API(Composition API),同时保留了选项式API(Options API)。两种 API 风格都能够覆盖大部分的应用场景。它们只是同一个底层系统所提供的两套不同的接口。实际…...
React配置代理的5种方法
React配置代理的五种方法的介绍 使用create-react-app的代理配置: 使用场景:适用于使用create-react-app创建的React项目,特别是小型项目或快速原型开发。优点:配置简单,无需额外安装依赖,适合快速开发和简…...
皮卡丘靶场搭建遇到的问题大全
该博客记录我在安装皮卡丘靶场中遇到的一些问题。 1、 phpstudy_pro启动Mysql失败 自己电脑开启了mysql服务,使用winr,services.msc,找到自己的mysql服务,关闭。再次尝试使用phpstudy_pro启动mysql,成功解决。 2、皮…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
