05 EXTI外部中断

一、中断系统

  1. 中断系统:管理和执行中断的逻辑结构。
  2. 中断:在主程序运行过程中,出现了特定的中断触发条件——中断源,使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行
    • 中断的作用:极大的提高程序的效率
      比如:
      • 对于外部中断来说,可以是引脚发生了电平跳变;
      • 对于定时器来说,可以是定时的时间到了;
      • 对于串口通信来说,可以是接收到了数据。
  3. 中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源。
    中断优先级就是中断的紧急程度,是我们根据程序设计的需求自己设置的。
    • 中断优先级的作用:为了在多个中断同时申请时判断一下应该先处理哪个。
      如果事件非常紧急,就把优先级设置高一些;如果不是那么紧急,就可以把优先级设置低一些。
      这样可以更好的安排这些中断事件,防止紧急的事件被别的中断耽误。
  4. 中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回。
    • 中断嵌套就是把中断程序再次中断的现象。
    • 中断嵌套是为了照顾非常紧急的中断的,如果现在CPU已经在执行某个中断程序了,这时又发生了一个非常紧急的中断,那这个中断就可以把当前的中断程序进行二次中断,这样新的紧急中断就可以立即被执行了。
    • 能否进行中断嵌套也是由中断优先级来决定的。

中断执行流程

在这里插入图片描述

二、STM32中断

  • 68个可屏蔽中断通道(即中断源),包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设。
  • 使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级。
    在这里插入图片描述
  • 灰色——内核的中断——了解
    • 复位中断:当产生复位事件时,程序就会自动执行复位中断函数,即复位后程序开始执行的位置
    • NMI不可屏蔽中断
    • 硬件失效
    • 存储管理
    • 总线错误
    • 错误应用
    • 等等
  • 白色——STM32外设中断
    • 窗口看门狗:监测程序运行状态的终端
    • PVD电源电压监测:如果供电电压不足,PVD电路就会申请中断
  • 中断的地址:
    • 因为程序中的中断函数的地址是由编译器来分配的,是不固定的,但中断跳转由于硬件的限制,只能跳到固定的地址执行程序。
    • 所以为了能让硬件跳转到一个不固定的中断函数里,就需要在内存中定义一个地址的列表。
    • 这个列表地址是固定的,中断发生后就跳到这个固定位置,然后在这个固定位置由编译器再加上一条跳转到中断函数的代码,这样中断跳转就可以跳到任意位置了。
    • 这个中断地址的列表就叫中断向量表,相当于中断跳转的一个跳板。

1. NVIC

NVIC 嵌套中断向量控制器

  • STM32中用来管理中断、分配优先级的
  • NVIC是一个内核外设,是CPU的小助手
  • NVIC有很多输入口,可以接多个中断线路;NVIC只有一个输出口。
  • 一个外设可能会同时占用多个中断通道,所以有n条线。NVIC根据每个中断的优先级分配中断的先后顺序,之后通过输出口告诉CPU该处理哪个。

(2)NVIC基本结构

在这里插入图片描述

(3)NVIC优先级分组

抢占优先级——可以看作插队
响应优先级——中断嵌套

  • NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级低4-n位的响应优先级

    4位二进制:0到15的数,对应16个优先级
    优先级的数:值越小优先级越高,0就是最高优先级

  • 抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队
    在这里插入图片描述

三、EXTI简介

  • EXTI(Extern Interrupt)外部中断
  • EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
  • 支持的触发方式:上升沿/下降沿/双边沿/软件触发
  • 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断(PA0和PB0不能同时用)
  • 外部中断占用的通道数(共20个):16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
  • 触发响应方式:中断响应/事件响应

1.EXTI基本结构

在这里插入图片描述
NVIC 中断响应
其他外设 事件响应

2.AFIO复用IO口

  • AFIO主要用于引脚复用功能的选择和重定义
—— 数据选择器的作用
  • 在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择

    在这里插入图片描述

3.EXTI框图

在这里插入图片描述

或门:多个输入一个输出,任意一个为1,就可以输出1
与门:多个输入一个输出,所有均为1,才可以输出1
非门:一个输入一个输出,输入1就输出0,输入0就输出1
数据选择器:多个输入一个输出

四、旋转编码器简介

  • 旋转编码器:用来测量位置、速度或旋转方向的装置,当其旋转轴旋转时,其输出端可以输出与旋转速度和方向对应的方波信号,读取方波信号的频率和相位信息即可得知旋转轴的速度和方向
  • 类型:机械触点式/霍尔传感器式/光栅式

    在这里插入图片描述

硬件电路

在这里插入图片描述
在这里插入图片描述

五、实操

5.1 对射式红外传感器计次

接线图

在这里插入图片描述

代码实现

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"

int main(void)
{
	OLED_Init();
	CountSensor_Init();
	
	OLED_ShowString(1, 1, "Count:");
	
	while (1)
	{
		OLED_ShowNum(1, 7, CountSensor_Get(), 5);
	}
}

CountSensor.c / .h

#include "stm32f10x.h"                  // Device header

uint16_t CountSensor_Count;

/**
  * @brief 初始化 对射式红外传感器
  * @param  无
  * @retval 无
  */
void CountSensor_Init(void)
{
	//1.配置RCC —— 把涉及的外设的时钟都打开
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	//2.配置GPIO —— 选择端口为输入模式
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//3.配置AFIO
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
	
	//4.配置EXTI —— 选择边沿触发方式、触发响应方式
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line14;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructure);
	
	//5.配置NVIC —— 选择合适优先级
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	//6.通过NVIC外部中断信号进入CPU
	
}

/**
  * @brief 读取对射式红外传感器的当前值
  * @param  无
  * @retval CountSensor_Count
  */
uint16_t CountSensor_Get(void)
{
	return CountSensor_Count;
}

/**
  * @brief 中断函数
  * @param  无
  * @retval 无
  */
void EXTI15_10_IRQHandler(void)
{
	//1.中断标志位的判断
	if(EXTI_GetITStatus(EXTI_Line14) == SET)
	{
		//如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
		{
			CountSensor_Count ++;
		}
		
		//2.清楚中断标志位
		EXTI_ClearITPendingBit(EXTI_Line14);
	}
}

#ifndef __COUNT_SENSOR_H
#define __COUNT_SENSOR_H

void CountSensor_Init(void);
uint16_t CountSensor_Get(void);

#endif

程序现象

  • 程序启动时,OLED屏幕上会显示"Count:"字符串
  • 之后,每挡一次传感器,计数就会+1,并将这个数据更新显示在OLED屏幕的指定位置。
  • 如果EXTI_Trigger配置为下降沿触发EXTI_Trigger_Falling,在移开挡光片时触发中断,计数+1
  • 如果EXTI_Trigger配置为上升沿触发EXTI_Trigger_Rising,在遮挡时触发中断,计数+1
  • 如果EXTI_Trigger配置为双边沿触发EXTI_Trigger_Rising_Falling,在遮挡和移开挡光片时均触发中断,计数+1

5.2 旋转编码器计次

接线图

在这里插入图片描述

代码实现

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Encoder.h"

int16_t Num;

int main(void)
{
	OLED_Init();
	Encoder_Init();
	
	OLED_ShowString(1, 1, "Num:");
	
	while (1)
	{
		Num += Encoder_Get();	//Encoder_Get函数返回的是调用该函数的间隔里,旋转编码器产生的正负脉冲数,所以返回值直接+=给Num
		OLED_ShowNum(1, 5, Num, 5);
	}
}

Encoder.c / .h

#include "stm32f10x.h"                  // Device header

int16_t Encoder_Count;

void Encoder_Init(void)
{
	//1.配置RCC —— 把涉及的外设的时钟都打开
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	//2.配置GPIO —— 选择端口为输入模式
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//3.配置AFIO
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
	
	//4.配置EXTI —— 选择边沿触发方式、触发响应方式
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructure);
	
	//5.配置NVIC —— 选择合适优先级
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&NVIC_InitStructure);
	
	//6.通过NVIC外部中断信号进入CPU

}


int16_t Encoder_Get(void)
{
	int16_t Temp;
	Temp = Encoder_Count;
	Encoder_Count = 0;
	return Temp;
}

void EXTI0_IRQHandler(void)
{
	//1.中断标志位的判断
	if(EXTI_GetITStatus(EXTI_Line0) == SET)
	{
		//如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
		{
			if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
			{
				Encoder_Count --;
			}
		}
		//2.清楚中断标志位
		EXTI_ClearITPendingBit(EXTI_Line0);
	}
}

void EXTI1_IRQHandler(void)
{
	//1.中断标志位的判断
	if(EXTI_GetITStatus(EXTI_Line1) == SET)
	{
		//如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
		{
			if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
			{
				Encoder_Count --;
			}
		}
		
		//2.清楚中断标志位
		EXTI_ClearITPendingBit(EXTI_Line1);
	}
}
#ifndef __ENCODER_H
#define __ENCODER_H

void Encoder_Init(void);
int16_t Encoder_Get(void);

#endif

程序现象

  • 程序启动时,OLED屏幕上会显示"Num:"字符串
  • 向右转,数字增加;向左转,数字减小。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux配置jdk、tomcat、mysql离线安装与启动

目录 1.jdk安装 2.tomcat的安装(开机自启动) 3.MySQL的安装 4.连接项目 1.jdk安装 上传jdk安装包 jdk-8u151-linux-x64.tar.gz 进入opt目录,将安装包拖进去 解压安装包 这里需要解压到usr/local目录下,在这里我新建一个文件夹…

普中51单片机学习(DA转换)

DA数模转换 分辨率 分辨率是指输入数字量的最低有效位(LSB)发生变化时,所对应的输出模拟量(电压或电流)的变化量。它反映了输出模拟量的最小变化值。 分辨率与输入数字量的位数有确定的关系,可以表示成FS …

FariyGUI × Cocos Creator 3.x 弹窗制作

在fgui里制作一个弹窗 新建一个按钮,作为返回按钮 新建一个标签 做成这个样子 其中包含两个节点,名称分别为title和closeButton 可以阅读fgui的源码window.js得到,closeButton按钮只需要输入名称即可在contentPane设置时自动绑定。 且会…

使用 React 和 MUI 创建多选 Checkbox 树组件

在本篇博客中,我们将使用 React 和 MUI(Material-UI)库来创建一个多选 Checkbox 树组件。该组件可以用于展示树形结构的数据,并允许用户选择多个节点。 前提 在开始之前,确保你已经安装了以下依赖: Reac…

汇编反外挂

在软件保护领域,尤其是游戏保护中,反外挂是一个重要的议题。外挂通常指的是一种第三方软件,它可以修改游戏数据、操作游戏内存或提供其他作弊功能,从而给玩家带来不公平的优势。为了打击外挂,游戏开发者会采取一系列措…

计算机网络-网络互联

文章目录 网络互联网络互联方法LAN-LAN:网桥及其互连原理使用网桥实现LAN-LAN使用交换机扩展局域网使用路由器连接局域网 LAN-WANWAN-WAN路由选择算法非自适应路由选择算法自适应路由选择算法广播路由选择算法:分层路由选择算法 网络互联 网络互联是指利…

数据存储-文件存储

一、CSV文件存储 csv是python的标准库 列表数据写入csv文件 import csvheader [班级, 姓名, 性别, 手机号, QQ] # 二维数组 rows [[学习一班, 大娃, 男, a130111111122, 987456123],[学习二班, 二娃, 女, a130111111123, 987456155],[学习三班, 三娃, 男, a130111111124, …

Javase补充-Arrays类的常用方法汇总

文章目录 一 . 排序方法二 . 查找方法三 . 判断是否相等的方法四 . 拷贝方法五 . 填充方法 一 . 排序方法 我们第一个要介绍的就是sort方法 这个排序实现的底层逻辑应该是十分复杂的,以我们目前的水平体系应该无法理解,我们今天尝试用我们可以理解的一种排序算法,插入排序来模…

jQuery瀑布流画廊,瀑布流动态加载

jQuery瀑布流画廊&#xff0c;瀑布流动态加载 效果展示 手机布局 jQuery瀑布流动态加载 HTML代码片段 <!-- mediabanner --><div class"mediabanner"><img src"img/mediabanner.jpg" class"bg"/><div class"text&qu…

纽约纳斯达克大屏投放受众群体有哪些-大舍传媒

纽约纳斯达克大屏投放受众群体有哪些-大舍传媒 1. 纳斯达克大屏的概述 纳斯达克大屏是全球金融市场中最出名的电子交易平台之一。作为一个重要的金融信息传递渠道&#xff0c;纳斯达克大屏吸引了来自全球的投资者的目光。在这个巨大的投放平台上&#xff0c;大舍传媒希望为客…

Stable Diffusion 3的到来巩固了 AI 图像对抗 Sora 和 Gemini 的早期领先优势

Stability AI 将其更改为 Stable Diffusion 3。VentureBeat 报道称&#xff0c;Stability AI 的下一代旗舰 AI 图像生成模型将使用类似于 OpenAI 的 Sora 的扩散变压器框架。其当前模型仅依赖于扩散架构。虽然尚未发布&#xff0c;但您可以在等候名单中注册。 官方网址链接&am…

【JavaScript 漫游】【020】DOM 常用知识点总结

文章简介 DOM 是 JavaScript 操作网页的接口&#xff0c;全称为文档对象模型&#xff08;Document Object Model&#xff09;。DOM 操作是 JavaScript 最常见的任务&#xff0c;离开了 DOM&#xff0c;JavaScript 就无法操作网页。 本篇文章为【JavaScript 漫游】专栏的第 02…

设计模式--单例模式--懒汉饿汉

单例模式 单例模式(Singleton)&#xff0c;保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。 单例模式 通常我们可以让一个全局变量使得一个对象被访问&#xff0c;但它不能防止你实例化多个对象。一个最好的办法就是&#xff0c;让类自身负责保存它的唯一实…

抖音数据抓取工具|短视频下载工具|视频内容提取软件

一、开发背景&#xff1a; 随着抖音平台的流行&#xff0c;越来越多的人希望能够下载抖音视频以进行个人收藏或分享。然而&#xff0c;目前在网上找到的抖音视频下载工具功能单一&#xff0c;操作繁琐&#xff0c;无法满足用户的需求。因此&#xff0c;我们决定开发一款功能强大…

完美解决ubuntu+windows双系统下时间不正确问题

在同一台电脑上安装ubuntuwindows双系统时&#xff0c;会出现某个系统的时间不正确的问题&#xff0c;而由于windows同步时间实在是太慢了&#xff0c;如果不去解决&#xff0c;windows上的时间大概率一直都是不对的。 原因分析 windows采用LocalTime机制设置时间&#xff0c…

挑战杯 基于大数据的股票量化分析与股价预测系统

文章目录 0 前言1 课题背景2 实现效果3 设计原理QTChartsarma模型预测K-means聚类算法算法实现关键问题说明 4 部分核心代码5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于大数据的股票量化分析与股价预测系统 该项目较为新颖…

onlyoffice api开发

编写代码 按照https://api.onlyoffice.com/editors/basic编写代码 <html> <head><meta charset"UTF-8"><meta name"viewport"content"widthdevice-width, user-scalableno, initial-scale1.0, maximum-scale1.0, minimum-scal…

【编译原理】用Python实现LR(0)语法分析

实验内容 对于给定的如下文法&#xff0c;编写调试一个上下文无关文法的LR(0)分析程序。 文法G’为&#xff1a; S → E S\to E S→E E → a A E\to aA E→aA E → b B E \to bB E→bB A → c A A\to cA A→cA A → d A\to d A→d B → c B B\to cB B→cB B → d B\to …

【C#】CNC 机器人的刀具路径生成软件PathCAM源码解析-Geometry

1. Loaders 1.1 DAE_Loader.cs 1.2 OBJ_Loader.cs 1.3 STL_Loader.cs 2. AnalyzedTriangleMesh.cs AnalyzedTriangleMesh类是一个用于分析和处理三角形网格&#xff0c;可以被用于将网格拆分为更小的部件或者识别特定特征的对象&#xff0c;如打印准备或几何分析&#xff0c;非…

网络原理——HTTP

1. 什么是HTTP协议 HTTP是应用层的协议。Java最主要的应用场景是做网站&#xff0c;而网站由 后端&#xff08;HTTP服务器&#xff09; 和 前端&#xff08;浏览器&#xff09;组成&#xff0c;HTTP协议就是负责这里后端和前端的数据交互。 HTTP3.0 之前在传输层是通过 TCP传…