【STM32教程】第四章 STM32的外部中断EXTI

news2024/12/24 7:16:24

案例代码及相关资料下载链接:

链接: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);
 }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/994506.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

创建的源文件后缀不是.c,在一些编译器上不能编译

问题描述: 源文件的名字和后缀写的比较随意,后缀不是.c,代码没有语法高亮,可能在一些编译器上不能编译通过。 现象: 解决办法: C语言代码中我们有约定:源文件的后缀是.c,头文件的后…

Java基础之static关键字

目录 静态的特点第一章、静态代码块第二章、静态属性第三章、静态方法调用静态方法时静态方法中调用非静态方法时 第四章、static关键字与其他关键字 友情提醒 先看文章目录,大致了解文章知识点结构,点击文章目录可直接跳转到文章指定位置。 静态的特点…

Jenkins 页面部分显示Http状态403 被禁止

前言 生产环境Jenkins部署了一段时间了,结果今天在流水线配置中,部分页面显示Jenkins 页面部分显示Http状态403 被禁止,修改配置点击保存之后偶尔也会出现这个。 问题 以下是问题图片 解决 在全局安全配置里面,勾选上启用代…

01背包优化 —— 滚动数组

题目:【模板】01背包_牛客题霸_牛客网 (nowcoder.com) 优化原理: (从右往左!!) 注意:

Maven打包错误:Please refer to XXXXX for the individual test results._zhizhiqiuya

Please refer to XXXXX for the individual test results._zhizhiqiuya 错误原因&#xff1a; 项目开发中没有编写测试&#xff0c;打包过程中test检测错误 解决方案&#xff1a; 跳过测试单元 修改pom文件 <build><plugins><!-- maven 打包时跳过测试 -->…

【逐步剖C++】-第一章-C++类和对象(上)

前言&#xff1a;本文主要介绍有关C入门需掌握的基础知识&#xff0c;包括但不限于以下几个方面&#xff0c;这里是文章导图&#xff1a; 本文较长&#xff0c;内容较多&#xff0c;大家可以根据需求跳转到自己感兴趣的部分&#xff0c;希望能对读者有一些帮助 那么本文也主要…

时序预测 | MATLAB实现ARMA自回归移动平均模型时间序列预测

时序预测 | MATLAB实现ARMA自回归移动平均模型时间序列预测 目录 时序预测 | MATLAB实现ARMA自回归移动平均模型时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现ARMA时间序列预测&#xff08;完整源码和数据&#xff09; 本程序基于MATLAB的armax函…

【pdf密码】PDF文件带有密码,该如何编辑文件?

打开PDF文件的时候&#xff0c;没有提示带有密码&#xff0c;但是打开文件之后发现没有办法编辑PDF文件&#xff0c;这个是因为PDF文件设置了限制编辑&#xff0c;我们需要将限制取消才能够编辑文件。 那么&#xff0c;我们应该如何取消密码&#xff0c;编辑文件呢&#xff1f…

使用React Hooks实现表格搜索功能

React Hooks是React 16.8版本引入的新特性&#xff0c;它的作用是为函数组件提供了状态管理和副作用处理的能力。 在React之前&#xff0c;函数组件被限制在只能使用无状态的函数组件&#xff0c;无法使用状态和生命周期方法。Hooks的引入解决了这个限制&#xff0c;使得函数组…

华为全光园区商业市场解决方案

随着全球碳中和实践发展&#xff0c;光进铜退是必然发展趋势&#xff0c;园区网络全光化已经成为新一代智慧园区的新名片。相较传统网络方案&#xff0c;全光园区采用光纤下沉&#xff0c;将光纤从弱电机房延伸到每个房间&#xff0c;每个桌面&#xff0c;每个机器&#xff0c;…

txt实现日期计算器前端代码【搬代码】

使用txt文件实现日期计算器 操作步骤&#xff1a; 1.首先在桌面创建txt文本文档 2.打开文本复制下面代码到文本中 3.修改文本的txt为html 4.右键该html文本&#xff0c;打开方式浏览器&#xff0c;结果如下 5.当然也可以作用于idea 此处是所有代码&#xff0c;复制粘贴即…

上手SpringBoot

设置Maven镜像为阿里云 找到Maven的目录所在位置找到conf目录找到settings.xml文件 找到Maven的目录所在位置&#xff1a;去idea 的设置中 直接搜索Maven 找到conf目录 修改Maven本地仓库的地址 地址自定义 修改Maven的镜像为阿里云镜像 <mirror><id>nexus-aliy…

app源代码安全检测的重要性

源代码审计 app软件代码漏洞扫描&#xff08;源代码安全检测&#xff09;是从安全的角度对代码进行安全测试和评估。同时结合丰富的安全知识、编程经验和测试技术&#xff0c;采用静态分析和人工审查的方法&#xff0c;发现代码架构和编码中的安全漏洞&#xff0c;在代码之前将…

LeetCode 297. Serialize and Deserialize Binary Tree【树,DFS,BFS,设计,二叉树,字符串】困难

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

LeetCode 428. Serialize and Deserialize N-ary Tree【树,BFS,DFS】困难

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

华为倒逼苹果?走出舒适圈积极创新,苹果推出首批CIS堆叠式手机

9月9日消息&#xff0c;苹果公司最近推出了iPhone 15系列&#xff0c;这是业内首批搭载CIS堆叠式传感器的手机。这一消息得到了相关业内人士的关注。知名分析师郭明錤认为&#xff0c;尽管美国施加了制裁&#xff0c;在一些方面对苹果的影响是负面的&#xff0c;但华为的归来将…

Spring-MVC的文件上传下载,及插件的使用(让项目开发更节省时间)

目录 一、概述 ( 1 ) 介绍 ( 2 ) 讲述 二、上传 三、下载 四、jrebel的使用 五、多文件上传 给我们带来什么收获 一、概述 ( 1 ) 介绍 Spring MVC的文件上传下载是指在Spring MVC框架中实现文件的上传和下载功能。文件上传是指将本地计算机上的文件上传到服务器端…

一种基于注意机制的快速、鲁棒的混合气体识别和浓度检测算法,配备了具有双损失函数的递归神经网络

A fast and robust mixture gases identification and concentration detection algorithm based on attention mechanism equipped recurrent neural network with double loss function 摘要 提出一个由注意力机制组成的电子鼻系统。首先采用端到端的编码器译码器&#xff…

987. 二叉树的垂序遍历

987. 二叉树的垂序遍历 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a;对中文的支持有点不友好IDEA 原题链接&#xff1a; 987. 二叉树的垂序遍历 https://leetcode.cn/problems/vertical-order-traversal-of-a-binary-tree/descriptio…

2.3 Java中的运算符

运算符&#xff0c;是表示各种不同运算的符号。 运算符按功能分为算术运算符、逻辑运算符、关系运算符、赋值运算符、位运算符等。 1. 算术运算符 算术运算符一般用于对整型数和浮点型数运算。 运算符 运算 范例 结果 正号 3 3 - 负号 b4;-b -4 加 55 10 …