STM32-EXTI外部中断

目录

一、中断系统

二、STM32中断

三、NVIC(嵌套中断向量控制器)基本结构

四、NVIC优先级分组

五、EXTI外部中断

5.1 外部中断基本知识

5.2 外部中断(EXTI)基本结构

​编辑

5.2.1开发步骤: 

5.3 AFIO复用IO口

5.4 EXTI内部框图

六、AFIO库函数

七、EXTI库函数 

八、NVIC库函数

九、中断函数

以上函数具体使用请参考”第十章、实验“ 

十、实验

10.1对射式红外传感器计次

10.2旋转编码器计次

十一、中断编程建议


一、中断系统

中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行

中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源

中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回

二、STM32中断

 68个可屏蔽中断通道,包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设

使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级

三、NVIC(嵌套中断向量控制器)基本结构

作用:统一分配中断优先级和管理中断

四、NVIC优先级分组

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

抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队

五、EXTI外部中断

5.1 外部中断基本知识

①EXTI(Extern Interrupt)外部中断

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

中断响应:引脚电平变化触发中断

事件响应:不触发中断,触发其他外设操作

5.2 外部中断(EXTI)基本结构

5.2.1开发步骤: 

①配置RCC,把涉及到的外设时钟都打开

②配置GPIO,选择端口为输入模式

③配置AFIO,选择用的某一路GPIO,连接到后面的EXTI

④配置EXTI,选择边沿触发方式、触发响应方式(中断响应/事件响应)

⑤配置NVIC,给中断选择合适的优先级

5.3 AFIO复用IO口

AFIO主要用于引脚复用功能的选择和重定义

在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择

5.4 EXTI内部框图

六、AFIO库函数

void GPIO_AFIODeInit(void);//复位AFIO

//配置AFIO事件输出功能

void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState);

/*下面两个重要*/
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);

//引脚重映射,第一个参数:重映射的方式;第二个参数:新的状态
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);

//配置AFIO的数据选择器,本节中断用到的函数


void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);

//以太网相关

AFIO中断选择函数详解

void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); 

第一个参数:GPIO_PortSourceGPIOx where x can be (A..G)

第二个参数:GPIO_PinSourcex where x can be (0..15)

七、EXTI库函数 

void EXTI_DeInit(void);//清除所有EXTI配置,复位
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);//结构体方式初始化EXTI
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);//给结构体变量赋默认值


void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);//软件触发外部中断

/*主函数查看和清除标志位*/
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);//获取指定标志位是否被置1
void EXTI_ClearFlag(uint32_t EXTI_Line);//对置1的标志位清除

/*中断函数查看和清除标志位*/
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

八、NVIC库函数

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);//中断分组的方式,整个芯片只能用一种,最好放在主函数中
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);//结构体方式初始化NVIC

/*下面两个不常用*/
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);//设置中断向量表
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);//系统低功耗配置

九、中断函数

每个通道对应一个中断函数,在启动文件中可查看

开发技巧:

在中断函数中,先进行中断标志位的判断,确保是我们想要的中断源触发的函数;然后再使用清除标志位函数清除,否则会一直执行中断函数,在中断函数里卡死。

以上函数具体使用请参考”第十章、实验“ 

十、实验

10.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

#include "stm32f10x.h"                  // Device headeruint16_t CountSensor_Count;void CountSensor_Init(void)
{/*一、开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启APB2时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟/*二、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);/*三、AFIO配置*/GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);/*四、EXTI第14个线路配置为中断模式,下降沿触发,开启中断*/EXTI_InitTypeDef EXTI_InitStructure;EXTI_InitStructure.EXTI_Line = EXTI_Line14;//EXTI线EXTI_InitStructure.EXTI_LineCmd = ENABLE;//开启或关闭EXTIEXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式或者事件模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//指定触发信号的有效边沿EXTI_Init(&EXTI_InitStructure);/*五、配置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);
}uint16_t CountSensor_Get(void)
{return CountSensor_Count;
}void EXTI15_10_IRQHandler(void)
{if(EXTI_GetITStatus(EXTI_Line14) == SET)    //判断标志位,是否是EXTI_Line14触发的中断{CountSensor_Count++;  EXTI_ClearITPendingBit(EXTI_Line14);//清除标志位}}

CountSensor.h

#ifndef __COUNTSENSOR_H
#define __COUNTSENSOR_Hvoid CountSensor_Init(void);
uint16_t CountSensor_Get(void);#endif

10.2旋转编码器计次

 mian.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();OLED_ShowSignedNum(1,5,Num,5);  }
}

Encoder.c

#include "stm32f10x.h"                  // Device headerint16_t Encoder_Count;//无符号变量/*初始化操作*/
void Encoder_Init(void)
{/*一、开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启APB2时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟/*二、GPIO配置*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);/*三、AFIO配置*/GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);/*四、EXTI第0/1个线路配置为中断模式,下降沿触发,开启中断*/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);/*五、配置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);
}int16_t Encoder_Get(void)
{int16_t Temp;Temp = Encoder_Count;Encoder_Count = 0;return Temp;
}/*正转中断函数*/
void EXTI1_IRQHandler(void)
{if(EXTI_GetITStatus(EXTI_Line1) == SET)					//B相下降沿(中断){if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0)	//A相低电平{Encoder_Count ++;}EXTI_ClearITPendingBit(EXTI_Line1);}
}/*反转中断函数*/
void EXTI0_IRQHandler(void)
{if(EXTI_GetITStatus(EXTI_Line0) == SET)					//A相下降沿(中断){if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0)	//B相低电平{Encoder_Count --;}EXTI_ClearITPendingBit(EXTI_Line0);}
}

Encoder.h

#ifndef __ENCODER_H
#define __ENCODER_Hvoid Encoder_Init(void);
int16_t Encoder_Get(void);#endif

十一、中断编程建议

①在中断函数中,不要执行耗时过长的代码,中断函数要简短快速,不要执行Delay函数,防止主程序受到严重阻塞

②不要在主函数和中断函数中调用相同的函数或者操作同一个硬件

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

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

相关文章

ADAudit Plus:强大的网络安全卫士

随着数字化时代的不断发展,企业面临着越来越复杂和多样化的网络安全威胁。在这个信息爆炸的时代,保护组织的敏感信息和确保网络安全已经成为企业发展不可或缺的一环。为了更好地管理和监控网络安全,ADAudit Plus应运而生,成为网络…

ThreadLocal系列-ThreadLocalMap源码

1.ThreadLocalMap.Entry key&#xff1a;指向key的是弱引用 value&#xff1a;强引用 public class ThreadLocal<T> {static class ThreadLocalMap {/*** The entries in this hash map extend WeakReference, using* its main ref field as the key (which is always…

32、卷积参数 - 长宽方向的公式推导

有了前面三节的卷积基础 padding, stride, dilation 之后,大概就可以了解一个卷积算法的全貌了。 一个完整的卷积包含的输入和输出有: 输入图像,表示为[n, hi, wi, ci] 卷积核,表示为[co, kh, kw, ci] 输出特征图,表示为[n, ho, wo, co] 以上为卷积算法的两个输入 tensor…

【持更】python数据处理-学习笔记

1、读取excel /csv及指定sheet&#xff1a; pd.read_excel("路径",sheetname"xx") 修改列名df.rename 修改字符串类型到数字 pandas.to_numeric&#xff08;&#xff09; 2、删除drop、去重drop_duplicates &#xff08;1&#xff09;空值所在行/列 行&am…

Redis分布式锁有什么缺陷?

Redis分布式锁有什么缺陷&#xff1f; Redis 分布式锁不能解决超时的问题&#xff0c;分布式锁有一个超时时间&#xff0c;程序的执行如果超出了锁的超时时间就会出现问题。 1.Redis容易产生的几个问题&#xff1a; 2.锁未被释放 3.B锁被A锁释放了 4.数据库事务超时 5.锁过期了…

centos 7 卸载图形化界面步骤记录

centos7 服务器操作系统&#xff0c;挺小一配置&#xff0c;装了图形化界面&#xff0c;现在运行程序的时候跑不动了&#xff0c;我想这图形界面也没啥用&#xff0c;卸载了算了&#xff01; 卸载步骤 yum grouplist 查询已经安装的组件 可以看到 图形化界面 等是以分组存在的…

深入理解Spring IOC的工作流程

理解Spring IOC&#xff08;Inversion of Control&#xff09;的工作流程是理解Spring框架的核心之一。下面是Spring IOC的基本工作流程&#xff1a; 配置&#xff1a; 开发者通过XML配置文件、Java配置类或者注解等方式&#xff0c;定义应用中的Bean以及它们之间的依赖关系。这…

TCP数据粘包的处理

TCP数据粘包的处理 背锅侠TCP解决方案2.1 发送端2.2 接收端 背锅侠TCP 在前面介绍套接字通信的时候说到了TCP是传输层协议&#xff0c;它是一个面向连接的、安全的、流式传输协议。因为数据的传输是基于流的所以发送端和接收端每次处理的数据的量&#xff0c;处理数据的频率可…

Qt练习题

1.使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否…

代码随想录 96. 不同的二叉搜索树

题目 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;5 示例 2&#xff1a; 输入&#xff1a;n 1 输出&#xff1…

【Angular开发】Angular 16发布:发现前7大功能

Angular 于2023年5月3日发布了主要版本升级版Angular 16。作为一名Angular开发人员&#xff0c;我发现这次升级很有趣&#xff0c;因为与以前的版本相比有一些显著的改进。 因此&#xff0c;在本文中&#xff0c;我将讨论Angular 16的前7个特性&#xff0c;以便您更好地理解。…

机器学习基础介绍

百度百科&#xff1a; 机器学习是一门多领域交叉学科&#xff0c;涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为&#xff0c;以获取新的知识或技能&#xff0c;重新组织已有的知识结构使之不断改善自身的性能。 …

手工酸奶店如何选址?开在哪里比较合适?

手工酸奶店是一个非常受欢迎的创业项目&#xff0c;但想要成功开店&#xff0c;选址是非常重要的。 本人开酸奶店5年时间&#xff0c;下面我将为大家分享一些选址的小技巧&#xff0c;希望对大家有所帮助。&#xff08;可以点赞收藏&#xff0c;方便以后随时查阅&#xff09; …

入职字节外包一个月,我离职了。。。

有一种打工人的羡慕&#xff0c;叫做“大厂”。 真是年少不知大厂香&#xff0c;错把青春插稻秧。 但是&#xff0c;在深圳有一群比大厂员工更庞大的群体&#xff0c;他们顶着大厂的“名”&#xff0c;做着大厂的工作&#xff0c;还可以享受大厂的伙食&#xff0c;却没有大厂…

12.11 C++ 作业

完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和密码不匹配&#xf…

树根研习社|数据为王,洞察“工业数据采集”背后的价值与实践

一、工业数据采集是什么&#xff1f; 数据采集是将各种信息传感设备通过网络结合起来&#xff0c;实现任何时间、任何地点&#xff0c;人、机、物的互联互通。数据采集的主要的作用是&#xff1a; “翻译官”&#xff1a;不同程序语言的设备数据通过协议解析“翻译”为上层系…

淘宝权益玩法平台的Serverless化实践

通过对权益玩法平台现有业务应用的Serverless化改造&#xff0c;权益团队在双十一期间完美地支撑了业务需求&#xff0c;在研发效率、运维保障等方面都体现出了很高的价值和收益。 项目背景 淘宝权益平台是负责淘宝权益营销的核心团队&#xff0c;团队除了负责拉菲权益平台外&a…

1.cloud-微服务架构编码构建

1.微服务cloud整体聚合父工程 1.1 New Project 1.2 Maven选版本 1.3 字符编码 1.4 注解生效激活 主要为lombok中的Data 1.5 java编译版本选8 1.6 File Type过滤 *.hprof;*.idea;*.iml;*.pyc;*.pyo;*.rbc;*.yarb;*~;.DS_Store;.git;.hg;.svn;CVS;__pycache__;_svn;vssver.scc;v…

Nginx配置文件的基本用法

Nginx简介 1.1概述 Nginx是一个高性能的HTTP和反向代理服务器。 是一款轻量级的高性能的web服务器/反向代理服务器/电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器 单台物理服务器可支持30 000&#xff5e;50 000个并发请求。 1.2Nginx和Apache的优缺点 &#xff…

mybatis数据输出-insert操作时获取自增列的值给对应的属性赋值

jdbc-修改 水果库存系统的 BaseDao 的 executeUpdate 方法支持返回自增列-CSDN博客 1、建库建表 CREATE DATABASE mybatis-example;USE mybatis-example;CREATE TABLE t_emp(emp_id INT AUTO_INCREMENT,emp_name CHAR(100),emp_salary DOUBLE(10,5),PRIMARY KEY(emp_id) );INSE…