【STM32教程】第四章 STM32的外部中断EXTI
案例代码及相关资料下载链接:
链接:https://pan.baidu.com/s/1hsIibEmsB91xFclJd-YTYA?pwd=jauj
提取码:jauj
1 中断系统
1.1 中断的概念
中断系统的定义:中断是指在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行。
通俗来讲中断就是主程序在正常运行时,出现了中断触发条件,而中断触发的条件有很多:对于外部中断来讲可能是引脚的电平发生变化;对于定时器来讲可能是定时的时间到了;对于串口通信来讲可能是接收到了数据,当以上事件发生时,程序的执行就会从主程序中跳到中断程序中来执行中断程序,直到中断程序执行完成之后才会重新执行主程序。而使用中断系统最大的作用就是能够极大的提升程序的运行效率。
中断优先级:中断优先级建立在有多个中断源的时候,当有多个中断源出现时,CPU就要考虑率先执行哪个中断,中断就像做一件事的轻重比例,当有很多事情堆到眼前时候,通常先做情况最紧急的,再做稍次一点的,这样就会给中断确立执行的先后顺序,而多个中断的执行顺序的先后就被叫做中断优先级。
中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回,而中断嵌套的执行通常是由中断优先级来确定的。中断嵌套可以理解将一堆要做的事慢慢一个一个抛给你,而你要根据每个事情的紧急程度来决定在已经有的事情里先做哪一个。
中断执行的流程如下图所示:
在我们学习的STM32 中有68个可屏蔽中断通道(中断源),包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设(68个中断源是F1系列中最多的,而对于某个具体型号可能并没有这么多,所以中断源的数量以单片机的数据手册为准),这些中断源都使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级。(具体中断源如下表所示灰色部分为内核中断,不是灰色部分的为STM32的外设中断,具体图标手册中有)
NVIC结构:
基本结构图如下图所示:
NVIC的全称是Nested vectoredinterrupt controller,即嵌套向量中断控制器,在STM32中NVIC用来统一分配中断优先级和管理中断的,他是单片机内核外设,是用来帮助CPU处理中断分配和配置中断优先级的地方(为了让CPU高速运行),因为NVIC有多个输入口,所以能将单片机的外设中断都来接到NVIC上,而NVIC只有一个输出口这样就能通过对中断优先级的设置,来输出中断优先级高的,然后交给CPU让CPU优先执行中断优先级高的程序,这就是NVIC的基本作用。
NVIC优先级分组:
为了处理不同形式的优先级,NVIC会有优先级进行分组,而NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级,其属性编号越小,表明它的优先级别越高。抢占优先级,是指打断其他中断的属性,即因为具有这个属性会出现嵌套中断(在执行中断服务函数A 的过程中被中断B 打断,执行完中断服务函数B 再继续执行中断服务函数A),抢占属性由NVIC 的参数配置。而响应属性则应用在抢占属性相同的情况下,当两个中断向量的抢占优先级相同时,如果两个中断同时到达, 则先处理响应优先级高的中断,抢占优先级和响应优先级均相同的按中断号排队,数字小的先响应。(中断号是指上图中优先级的序号)
优先级的分组方式如下图所示:
注意在配置好NVIC的分组方式之后,配置优先级时,取值不能超过对应NVIC分组的取值范围。
1.2 外部中断的简介与配置
外部中断简介:
EXTI(Extern Interrupt)外部中断,EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序。
其触发方式有上升沿,下降沿,双边沿,软件触发四种。EXTI支持所有的GPIO口都可以触发中断,但是相同的Pin_不可以同时触发中断,例如PA1与PB1不能同时触发中断。EXTI有20个通道数,说明EXTI可以有20个中断源,其中包括16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤
醒;而EXTI响应方式有中断响应(申请中断让CPU执行中断函数),事件响应(中断响应时,外部中断信号不会传向CPU而是给到单片机外设,让单片机外设响应一个事件)。
外部中断的基本结构:
结构图如下图所示:
最左边是GPIO口的外设,由于每个GPIO都有16个通道当每个GPIO的引脚都占用一个那么EXTI的通道就会不够用,为了让相同的Pin_不同时触发中断,所以就有AFIO用来进行中断引脚的选择,相当于一个数据选择器,他可以从前面N个GPIO的16个引脚中选择其中一个接到后面的EXTI通道里面,所以就会有上面说的相同的Pin_不可以同时触发中断,因为对于相同的Pin_在经过AFIO之后只会有一个Pin_接到后面的EXTI通道上,例如:PA0,PB0,PC0,PD0,只有一个Pin_0可以接到EXTI的通道0上。而以上GPIO引脚通过EXTI上之后,就会分为两种输出,一种接到NVIC上,一种接到单片机外设上(也是对应的事件响应),这里EXTI的输出本来为20个但是由于ST公司想要节省引脚口,所以EXTI4之后的中断被五个为一组分在同一个通道里,所以EXTI5~9会触发同一个中断函数,EXTI10~15触发同一个中断函数,但是基于Hal库开发的STM32将这些中断函数写在了一起,所以所有中断通道都可以写在同一个中断函数里面,但是标准库必须根据不同的中断通道来判断到底能不能写在一起。
AFIO口的结构图如下:
此图原理就是将输入的不同GPIO相同的Pin_通过数据选择器来进行选择,最后只选择一个Pin_来接到EXTI通道上,具体如何选择就是通过配置AFIO_EXTRCRX寄存器的EXTIx位来进行选择,每个位代表不同的GPIO,这样就能以确定的位来确定是哪个GPIO的引脚会接到EXTIX的通道上面。
AFIO主要用于引脚复用功能的选择和重定义(数据选择器),在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择。
EXTI结构图
电平经过AFIO之后进入EXTI,首先要对该中断源的触发方式进行选择(上升沿触发/下降沿触发/双边沿触发)进入或门的输入,这里用或门进行输入的原因是因为触发方式也可以选择是软件触发,然后就会分成两路,接到NVIC中断控制器的是触发中断的,而接到脉冲发生器的是用来触发事件的。
先看触发中断这一路的,这里接的请求挂起寄存器相当于中断标志位,通过读取这个寄存器判断是哪个通道发出中断请求,如果给请求挂起寄存器置1,那么就会和中断屏蔽寄存器进入一个与门,然后进入NVIC中断控制器,这里与门和这个中断屏蔽寄存器相当于一个开关的作用,因为与门是如果输入有一个为0,那么输出一定为0,所以会通过控制中断屏蔽寄存器来控制是否响应中断。
事件触发这一路与中断触发大同小异,这里事件屏蔽寄存器和与门也充当开关的作用,通过与门之后接一个脉冲发生器,这个脉冲发生器的作用就是给一个电平脉冲是用来触发其他外设的。
上图中画斜杠写20的表示这里可以接20根线,连接20个通道,而APB总线和外设接口,单片机对于寄存器的访问就是借助APB总线来进行。
2实验演示
2.1 旋转编码器的简介
旋转编码器:用来测量位置、速度或旋转方向的装置,当其旋转轴旋转时,其输出端可以输出与旋转速度和方向对应的方波信号,读取方波信号的频率和相位信息即可得知旋转轴的速度和方向,通常有以下几种类型:机械触点式/霍尔传感器式/光栅式。
实物图如下:
左边第一个不能判断不能判断旋转方向,只能测位置和速度所以不经常使用,而剩下的就是我们本开发板自带的旋转编码器,由第三个拆解图可得他内部是通过金属触点来进行通断的,所以为机械式编码器,有左右两部分开关触点,其中左右两部分内侧较细的触点是连接在引脚B上,而剩下外侧的触点分别连在引脚A和C上,而中间的圆点为一个普通的按键,然后来看这个编码盘也是一系列像光栅一样的东西,但也是金属触点,在旋转时依次接通和断开两边的触点,而金属盘的位置也是经过设计可以让两侧触点的通断有九十度的相位差,
具体输出波形如下方两图所示(上图为正转时,下图为反转时)以下这样的正交波形就可以用来区别方向。
硬件电路图如下
2.2 对射式红外传感器计次
接线图如下:
实物图如下:
实验内容
本实验是对对射式红外传感的传感次数进行计次,通过用遮光片遮挡来对红外传感器传输进行计次,然后通过OLED屏幕来显示传感次数。并且对于中断触发方式的不同,计次方式也不同。
首先,配置STMCube MX
将GPIO口用来实现外部中断的配置为中断模式即PB14,由于OLED也要继续使用所以对OLED的引脚继续配置为输出模式即可:
在NVIC中勾选EXTI line[15:10] interrupts
对NVIC的中断分组方式选择方式2(哪一个随自己选择)
在GPIO这里对中断触发方式进行选择:
其他配置不变,生成工程即可。
代码部分:
HAL库关于外部中断的函数只有一个:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
具体模板用法如下:
HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if(GPIO_Pin==GPIO_PIN_1)//判断是哪个中断源{//执行中断函数__HAL_GPIO_EXTI_CLEAR_IT ( GPIO_Pin);//中断结束标志必须有不然会卡在中断中不能进入主程序}//Hal库中所有的中断函数都在这一个函数中进行if(GPIO_Pin==GPIO_PIN_3){}
}
CountSensor部分代码
#include "main.h"
#include "gpio.h"uint16_t Consensor_count;uint16_t CountSensor_Get(void)
{return Consensor_count;
}/*** 函数功能: 外部中断回调函数* 输入参数: GPIO_Pin:中断引脚* 返 回 值: 无* 说 明: 无*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if(GPIO_Pin==CountSensor_Pin){if(HAL_GPIO_ReadPin(CountSensor_GPIO_Port,CountSensor_Pin)== 1 )//下降沿有效计次即可{Consensor_count++;}__HAL_GPIO_EXTI_CLEAR_IT ( CountSensor_Pin);}
}
主函数部分代码
OLED_Init ();
OLED_ShowString (1,1,"Count:");
while (1)
{OLED_ShowNum (1,7,CountSensor_Get (),5);//如果有新的下降沿出现直接覆盖上一次的数字
}
2.3 旋转编码计次
接线图如下图所示:
实验内容:
对旋转编码器旋转进行计次,正转加加爱,反转减减,计得次数通过OLED来不断刷新。
STM32CubeMX配置:
对旋转编码器连接的引脚PB0与PB1配置为外部中断模式,给OLED连接的引脚PB8与PB9配置为输出模式,在NVIC选择分组方式,然后在下面勾选
EXTI line0 interrupt EXTI line1 interrupt 。
然后在GPIO里配置IO口的触发中断方式与输出模式,根据自身习惯来对IO口进行宏定义。
配置完成后,生成工程。
代码部分:
Encoder部分代码:
#include "main.h"
#include "gpio.h"uint16_t Encoder_Count;uint16_t Encoder_Get(void)
{uint16_t Temp;Temp = Encoder_Count ;Encoder_Count = 0;return Temp ;
}/*** 函数功能: 外部中断回调函数* 输入参数: GPIO_Pin:中断引脚* 返 回 值: 无* 说 明: 无*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if(GPIO_Pin==Count_Increase_Pin)//读取中断源{if(HAL_GPIO_ReadPin(Count_Increase_GPIO_Port , Count_Increase_Pin)==0 ){if(HAL_GPIO_ReadPin(Count_Decrease_GPIO_Port , Count_Decrease_Pin)== 0 )//旋转编码器向左转时Encoder_Count--;}__HAL_GPIO_EXTI_CLEAR_IT ( Count_Increase_Pin);//消除中断标志,由中断进入主函数}else if(GPIO_Pin==Count_Decrease_Pin){if(HAL_GPIO_ReadPin(Count_Decrease_GPIO_Port , Count_Decrease_Pin)== 0){if(HAL_GPIO_ReadPin(Count_Increase_GPIO_Port , Count_Increase_Pin)== 0 )//旋转编码器向右转时Encoder_Count++;}__HAL_GPIO_EXTI_CLEAR_IT ( Count_Decrease_Pin);//消除中断标志,由中断进入主函数
}
主函数部分代码:
in16_t Num;
OLED_Init();
OLED_ShowString (1,1,"Count:");while (1)
{/* USER CODE END WHILE *//* USER CODE BEGIN 3 */Num+=Encoder_Get();//时刻刷新计次OLED_ShowSignedNum(1,7,Num,5);}
}
相关文章:

【STM32教程】第四章 STM32的外部中断EXTI
案例代码及相关资料下载链接: 链接:https://pan.baidu.com/s/1hsIibEmsB91xFclJd-YTYA?pwdjauj 提取码:jauj 1 中断系统 1.1 中断的概念 中断系统的定义:中断是指在主程序运行过程中,出现了特定的中断触发条件…...
力扣第40天----第121题、第122题
# 力扣第40天----第121题、第122题 文章目录 一、第121题--买卖股票的最佳时机二、第122题--买卖股票的最佳时机II 一、第121题–买卖股票的最佳时机 分2种情况考虑,根据持有股票、不持有股票这2种情况,完成递推公式。另外,这里要求只买卖…...
Flask 使用 JWT(二)
在 Python 使用 JWT 主要的方案是 PyJWT 工具。 安装与基本使用 可以使用 pip 安装 PyJWT: $ pip install pyjwt编码与解码 编码函数 def encode( self, payload: Dict[str, Any], # payload 参数 key: str, …...

从0到1理解ChatGPT原理
目录 写在前面 1.Tansformer架构模型 2.ChatGPT原理 3.提示学习与大模型能力的涌现 3.1提示学习 3.2上下文学习 3.3思维链 4.行业参考建议 4.1拥抱变化 4.2定位清晰 4.3合规可控 4.4经验沉淀 机械工业出版社京东自购链接 写在前面 2022年11月30日,ChatG…...
如何解决 “Component cannot be used as a JSX component“
原因是react版本与types/react版本不一致导致的, 在tsconfig.json中加入以下代码,将依赖指向项目里的node_modules "paths": {"react": [ "./node_modules/types/react" ]}改完后代码大概是长这样的 {"compilerOptions": {..."…...

小程序自定义tabbar
前言 使用小程序默认的tabbar可以满足常规开发,但是满足不了个性化需求,如果想个性化开发就需要用到自定义tabbar,以下图为例子 一、在app.json配置 先按照以往默认的形式配置,如果中间的样式特殊则不需要配置 "tabBar": {&qu…...

分布式系统第五讲:分布式事务及实现方案
分布式系统第五讲:分布式事务及实现方案 事务是一个程序执行单元,里面的所有操作要么全部执行成功,要么全部执行失败。而分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。本…...

算法通关村17关 | 透析跳跃游戏
1. 跳跃游戏 题目 LeetCode55 给定一个非负整数数组,最初位于数组的第一个位置,数组中的每个元素代表你再该位置可以跳跃的最大长度,判断你是否能够达到最后一个位置。 思路 如果当前位置元素如果是3,我们无需考虑是跳几步&#…...

ARM接口编程—RTC(exynos 4412平台)
RTC简介 RTC(Real Time Clock)即实时时钟,它是一个可以为系统提供精确的时间基准的元器件,RTC一般采用精度较高的晶振作为时钟源,有些RTC为了在主电源掉电时还可以工作,需要外加电池供电。 RTC内部原理 RTC寄存器 RTC控制寄存器 …...

数据分享|WEKA信贷违约预测报告:用决策树、随机森林、支持向量机SVM、朴素贝叶斯、逻辑回归...
完整报告链接:http://tecdat.cn/?p28579 作者:Nuo Liu 数据变得越来越重要,其核心应用“预测”也成为互联网行业以及产业变革的重要力量。近年来网络 P2P借贷发展形势迅猛,一方面普通用户可以更加灵活、便快捷地获得中小额度的贷…...
逆市而行:如何在市场恐慌时保持冷静并抓住机会?
市场中的恐慌和波动是投资者所不可避免的。当市场出现恐慌情绪时,很多投资者会盲目跟从大众,导致决策出现错误。然而,聪明的投资者懂得在恐慌中保持冷静,并将其视为抓住机会的时机。本文将分享一些在市场恐慌时保持冷静并抓住机会…...
SpringBoot项目在Linux上启动、停止脚本
文章目录 SpringBoot项目在Linux上启动、停止脚本1. 在项目jar包同一目录,创建脚本xxx.sh【注: 和项目Jar同一目录】2. xxx.sh脚本内容,实际项目使用,只需修改jar包的名称:xxxxxx.jar3. 给xxx.sh赋予执行权限4. xxx.sh脚本的使用 …...

基于32位单片机的感应灯解决方案
感应灯是一种常见照明灯,提起感应灯,相信大家并不陌生, 它在一些公共场所、卫生间或者走廊等场所,使用的较为广泛,同时它使用起来也较为方便省电。“人来灯亮,人走灯灭”的特性,使他们在部分场景…...

机器学习——支持向量机(SVM)
机器学习——支持向量机(SVM) 文章目录 前言一、SVM算法原理1.1. SVM介绍1.2. 核函数(Kernel)介绍1.3. 算法和核函数的选择1.4. 算法步骤1.5. 分类和回归的选择 二、代码实现(SVM)1. SVR(回归&a…...

HTTP协议初识·下篇
介绍 承接上篇:HTTP协议初识中篇_清风玉骨的博客-CSDN博客 本篇内容: 长链接 网络病毒 cookie使用&session介绍 基本工具介绍 postman 模拟客户端请求 fiddler 本地抓包的软件 https介绍 https协议原理 为什么加密 怎么加密 CA证书介绍 数字签名介绍…...
c++ 类的实例化顺序
其他类对象有作为本类成员,先构造类中的其他类对象, 释放先执行本对象的析构函数再执行包含的类对象的析构函数 #include <iostream> #include <string.h> using namespace std;class Phone { public:Phone(string name):m_PName(name){…...

Vue自动生成二维码并可下载二维码
遇到一个需求,需要前端自行生成用户的个人名片分享二维码,并提供二维码下载功能。在网上找到很多解决方案,最终吭哧吭哧做完了,把它整理记录一下,方便后续学习使用!嘿嘿O(∩_∩)O~ 这个小东西有以下功能特点…...

应该下那个 ActiveMQ
最近在搞 ActiveMQ 的时候,发现有 2 个 ActiveMQ 可以下载。 应该下那个呢? JMS 即Java Message Service,是JavaEE的消息服务接口。 JMS主要有两个版本:1.1和2.0。 2.0和1.1相比,主要是简化了收发消息的代码。 所谓…...

【C语言】指针详解(3)
大家好,我是苏貝,本篇博客带大家了解指针(2),如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 目录 一.函数指针数组二.指向函数指针数组的指针(不重要)三.回调函数 一.函…...

告别HR管理繁琐,免费低代码平台来帮忙
编者按:本文着重介绍了使用免费且高效的低代码平台实现的HR管理系统在一般日常人力资源管理工作中的关键作用。 关键词:低代码平台、HR管理系统 1.HR管理系统有什么作用? HR管理系统作为一款数字化工具,可为企业提供全方位的人力资…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...