7、STM32的外部中断EXTI及NVIC中断优先级介绍(内附代码)

发布者:TranquilOasis最新更新时间:2022-04-21 来源: eefocus关键字:STM32  外部中断  EXTI  NVIC  中断优先级 手机看文章 扫描二维码
随时随地手机看文章

一、什么是中断?


打断当前的操作,执行中断需要做的事情。


中断的作用:中断机制不仅赋予了系统处理意外情况的能力,就可以“同时”完成多个任务,提高了并发“处理”能力。


和线程的区别:线程是同时执行多个任务,中断是停下来去执行其他的(注意优先级),执行完了再回来执行,


定时器才相当于线程,定一个时间,每到这个时间执行一次

二、中断概述


STM32F4并没有使用CM4内核的全部东西,而是只用了它的一部分。


STM32F40xx/STM32F41xx总共有92个中断


STM32F42xx/STM32F43xx则总共有96个中断


STM32F40xx/STM32F41xx的92个中断里面,包括10个内核中断和82个可屏蔽中断,具有16级可编程的中断优先级,而我们常用的就是这82个可屏蔽中断。


三、外部中断/事件线映射多达140个GPIO。

根据图文,发现我们的中断线总共有23根,其中16根是连接PA~PI引脚。 


STM32F4供IO使用的中断线只有16个:EXTI线0~15:对应外部IO口的输入中断。


剩下的七根是分别连接专用设备的:


 另外七根 EXTI 线连接方式如下:


● EXTI 线 16 连接到 PVD 输出


● EXTI 线 17 连接到 RTC 闹钟事件


● EXTI 线 18 连接到 USB OTG FS 唤醒事件


● EXTI 线 19 连接到以太网唤醒事件


● EXTI 线 20 连接到 USB OTG HS(在 FS 中配置)唤醒事件


● EXTI 线 21 连接到 RTC 入侵和时间戳事件


● EXTI 线 22 连接到 RTC 唤醒事件


四、中断服务函数分配


IO口外部中断在中断向量表中只分配了7个中断向量,也就是只能使用7个中断服务函数

从表中看出,外部中断线5~9分配一个中断向量,共用一个服务函数 外部中断线10~15分配一个中断向量,共用一个中断服务函数


中断服务函数列表如下:

五、设置中断优先级的分组


    1、中断优先级有两种:


        抢占(占先式)优先级 --》 第一序列                  响应(副)优先级 --》 第二序列


  2、抢占优先级 &响应优先级区别:


        高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。


        抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。


        抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。


        如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;

3、中断优先级设置步骤


//①系统运行后先设置中断优先级分组。调用函数:

 

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);整个系统执行中只设置一次中断分组。

 

//②针对每个中断,设置对应的抢占优先级和响应优先级:

 

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

③如果需要挂起/解挂,查看中断当前激活状态,分别调用相关函数即可


五、外部中断的一般配置步骤


①使能SYSCFG时钟:


    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);


②初始化IO口为输入。


    GPIO_Init();

③设置IO口与中断线的映射关系。


    void SYSCFG_EXTILineConfig();//通过设置SYSCFG寄存器,建立IO口和中断线的连接


④初始化线上中断,设置触发条件等。


    EXTI_Init();


⑤配置中断分组(NVIC),并使能中断。


    NVIC_Init();

⑥编写中断服务函数。


    EXTIx_IRQHandler();


且清除中断标志位


EXTI_ClearITPendingBit();//清除中断标志位是为了表示中断已经开始执行,可以接收下一个中断。


代码如下:


/**********************************************

*

*功能:四个按键中断

*

**********************************************/

#include "exti.h"

 

 

//外部中断初始化程序

//初始化PE2~4,PA0为中断输入.

void EXTI4_Init(void)

{

    NVIC_InitTypeDef   NVIC_InitStructure;

    EXTI_InitTypeDef   EXTI_InitStructure;

    GPIO_InitTypeDef  GPIO_InitStructure;

 

 

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOA,GPIOE时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟

 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //KEY0 KEY1 KEY2对应引脚

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉

    GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4

 

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);//PE4 连接到中断线4

 

    /* 配置EXTI_Line2,3,4 */

    EXTI_InitStructure.EXTI_Line = EXTI_Line4;

    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件

    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发

    EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能

    EXTI_Init(&EXTI_InitStructure);//配置

 

    NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//外部中断4

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级1

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道

    NVIC_Init(&NVIC_InitStructure);//配置   

}

 

 

void EXTI3_Init(void)

{

    NVIC_InitTypeDef   NVIC_InitStructure;

    EXTI_InitTypeDef   EXTI_InitStructure;

    GPIO_InitTypeDef  GPIO_InitStructure;

 

 

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOA,GPIOE时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟

 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //KEY0 KEY1 KEY2对应引脚

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉

    GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4

 

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);//PE4 连接到中断线4

 

 

    /* 配置EXTI_Line2,3,4 */

    EXTI_InitStructure.EXTI_Line = EXTI_Line3;

    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件

    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发

    EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能

    EXTI_Init(&EXTI_InitStructure);//配置

 

    NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;//外部中断4

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级1

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道

    NVIC_Init(&NVIC_InitStructure);//配置   

}

 

 

void EXTI2_Init(void)

{

    NVIC_InitTypeDef   NVIC_InitStructure;

    EXTI_InitTypeDef   EXTI_InitStructure;

    GPIO_InitTypeDef  GPIO_InitStructure;

 

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOA,GPIOE时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟

 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //KEY0 KEY1 KEY2对应引脚

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉

    GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4

 

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);//PE4 连接到中断线4

 

 

    /* 配置EXTI_Line2,3,4 */

    EXTI_InitStructure.EXTI_Line = EXTI_Line2;

    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件

    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发

    EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能

    EXTI_Init(&EXTI_InitStructure);//配置

 

    NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;//外部中断4

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级1

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道

    NVIC_Init(&NVIC_InitStructure);//配置   

}

 

 

void EXTI0_Init(void)

{

    NVIC_InitTypeDef   NVIC_InitStructure;

    EXTI_InitTypeDef   EXTI_InitStructure;

    GPIO_InitTypeDef  GPIO_InitStructure;

 

 

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA,GPIOE时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟

 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //KEY0 KEY1 KEY2对应引脚

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉

    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOE2,3,4

 

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//PE4 连接到中断线4

 

 

    /* 配置EXTI_Line2,3,4 */

    EXTI_InitStructure.EXTI_Line = EXTI_Line0;

    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件

    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发

    EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能

    EXTI_Init(&EXTI_InitStructure);//配置

 

    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断4

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级1

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道

    NVIC_Init(&NVIC_InitStructure);//配置   

}

 

 

//外部中断4服务程序

void EXTI4_IRQHandler(void)

{

     if(EXTI_GetITStatus(EXTI_Line4) != RESET)//判断是否置位

    {} 

    EXTI_ClearITPendingBit(EXTI_Line4);//清除LINE4上的中断标志位  

}

 

 

//外部中断3服务程序

void EXTI3_IRQHandler(void)

{

    delay_ms(15);

 

    EXTI_ClearITPendingBit(EXTI_Line3);//清除LINE4上的中断标志位  

}

 

 

//外部中断2服务程序

void EXTI2_IRQHandler(void)

    EXTI_ClearITPendingBit(EXTI_Line2);//清除LINE4上的中断标志位  

}

 

 

//外部中断0服务程序

void EXTI0_IRQHandler(void)

    EXTI_ClearITPendingBit(EXTI_Line1);//清除LINE4上的中断标志位  

}

关键字:STM32  外部中断  EXTI  NVIC  中断优先级 引用地址:7、STM32的外部中断EXTI及NVIC中断优先级介绍(内附代码)

上一篇:STM32CUBEIDE打印浮点数问题
下一篇:STM32的RTC的原理与使用(附代码)

推荐帖子

CKCWS-A90SA 谁有MDK注册机帮我产生一下
CKCWS-A90SA谁有MDK注册机帮我产生一下CKCWS-A90SA谁有MDK注册机帮我产生一下CKCWS-A90SA是什么?CKCWS-A90SA是本机电脑的CID,因为限制下载不了注册机,所以求助!回复沙发youki12345的帖子就是用Keil注册机来弄的回复沙发youki12345的帖子NQQ63-AMGVZ-QBEEE-59TLR-GA9ND-2WDKT谢谢回复5楼kumocw的帖子
suguoliu 微控制器 MCU
“POS机套件”中的器件,你将怎样发挥它的作用?
“POS机套件”中的器件,都很有特点,一部分是TI刚刚推出的新器件,性能及功能很好。TI这次活动将了放100套这样的套件,比例相当大。这些套件如果到了你手里,你将怎样发挥它的作用?有更具体的想法吗? “POS机套件”中的器件,你将怎样发挥它的作用?楼主的问题呢很好,还真不知道怎么怎样发挥它的作用,因为估计很多朋友还根本不知道它是个啥,,,谁了解的多,不妨来说一下放到DIY小组么~方案最重要,出了方案啥都好说~直接看看说明,手头搞的东西能用就直接上了原帖由shuigui于
dontium 模拟与混合信号
关于AMS1117 AD 输出电压求助
有一个这样的1117应用。不知道输出电压的计算公式是怎么样的?找了很多资料发现接法都不同。求助谢谢关于AMS1117AD输出电压求助看起来是个恒流源的应用,猜测而已测试了一下,貌似是恒流,哪么该怎么计算呢?是算电流还是电压的?看来是恒流的,只是不知道该怎么算电压电流这个的话,我记得datasheet中有对这些计算有解释的。您去下载它的datasheet,看看里面的内容就知道怎么计算了。R1是这个IC的负载电阻,在它上面的电压,等于其稳压值。它是变相的恒流电路。
xxhei PCB设计
【资料共享】33个毕业设计——单片机类
即将毕业的同学可以参考借鉴,33个毕业设计——单片机类!【资料共享】33个毕业设计——单片机类33个毕业设计——单片机类33个毕业设计——单片机类顶一下!谢谢楼主分享谢谢楼主分享顶一下好东西,看看能干嘛源码??谢谢楼主!很有用,学习学习谢谢楼主收下了,谢谢分享下载了为什么是0B呢,没有任何内容~最经在学习单片机,这下有材料可以做了太感谢了谢谢分享,下载看看先好东西,感谢分享哇塞碉堡了先谢谢,看一下希望有点意思东西不错,下来看看啊!多谢
zgzzlt 51单片机
关于消费电子产品的功能测试问题
本帖最后由jameswangsynnex于2015-3-320:00编辑楼上的可以多帖一些资料上来啊Re:关于消费电子产品的功能测试问题本帖最后由jameswangsynnex于2015-3-320:00编辑没有人顶了,打击积极性嘛!回复:关于消费电子产品的功能测试问题
cloudy313 移动便携
【行空板 Python编程学习主控板】使用陀螺仪和语音识别的星球大战BB-8机器人控制器
目录:零、前言一、设计规划二、六轴传感器三、麦克风与语音识别四、按键处理五、BB-8机器人的控制方式六、行空板控制BB-8机器人七、BB-8机器人控制器系统八、实际操作效果演示九、总结零、前言在申请行空板的时候,我提交的测评计划是:准备基于此开发板,使用Python语言,基于板载的加速度传感器和麦克风,构建一个星球大战之BB-8机器人控制系统,其具体功能如下: 将星空开发板变身手持控制器,通过保持平衡
HonestQiao 嵌入式系统
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved