STM32的外部中断EXTI及NVIC中断优先级介绍

发布者:Serendipitous55最新更新时间:2018-12-11 来源: 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_Line4);//清除LINE4上的中断标志位  

}

 

 

//外部中断2服务程序

void EXTI2_IRQHandler(void)

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

}

 

 

//外部中断0服务程序

void EXTI0_IRQHandler(void)

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

}


关键字:STM32  外部中断  EXTI  NVIC  中断优先级 引用地址:STM32的外部中断EXTI及NVIC中断优先级介绍

上一篇:Cortex-M0 LPC11C14中断控制器
下一篇:LPC824 一种IAP实现方法

推荐阅读最新更新时间:2024-03-16 16:19

STM32 USB 使用芯片内部flash模拟U盘
这次是实现一个使用STM32内部的flash模拟一个U盘。我使用的STM32芯片是STM32F103ZE,该芯片有512K的内部flash,本次工程,我准备用最后的400K空间来模拟一个U盘。本次的工程在之前用NAND或SD卡模拟U盘的工程基础上进行修改。 首次要做的是在外设库组中添加stm32f10x_flash.c文件,因为涉及到内部flash,所以必须添加此文件。接下去,需要修改的文件只有mass_mal.c和memory.c两个了。 先来讲讲memory.c,这个文件修改量很小。在函数的前面,我们可以看到有个:uint32_t Data_Buffer ;数组的定义,该数组的数组元素个数,跟大家所使用的存储器的块大小有
[单片机]
<font color='red'>STM32</font> USB 使用芯片内部flash模拟U盘
STM32 | 通俗易懂地串口通讯解析
平时使用串口打印出现乱码的绝大部分原因是串口波特率没对。那么我们怎么测量实际的波特率呢?在这之前,顺便一起回顾一下波特率的概念。 什么是波特率、比特率? 比特率(Bitrate)表示每秒钟传输的二进制位数,单位为比特每秒(bit/s)。 波特率(Baudrate)表示每秒钟传送的码元符号的个数,是衡量数据传送速率的指标。 码元是通讯信号调制的概念,通讯中常用时间间隔相同的符号来表示一个二进制数字,这样的信号称为码元。 常见的通讯传输中,用 0V 表示数字 0, 5V 表示数字 1,那么一个码元可以表示两种状态 0 和 1,所以一个码元等于一个二进制比特位,此时波特率的大小与比特率一致。 如果在通讯传输中,有 0V、
[单片机]
<font color='red'>STM32</font> | 通俗易懂地串口通讯解析
STM32】系统时钟RCC详解(超详细,超全面)
1什么是时钟 时钟是单片机运行的基础,时钟信号推动单片机内各个部分执行相应的指令。时钟系统就是CPU的脉搏,决定cpu速率,像人的心跳一样 只有有了心跳,人才能做其他的事情,而单片机有了时钟,才能够运行执行指令,才能够做其他的处理 (点灯,串口,ADC),时钟的重要性不言而喻。 为什么 STM32 要有多个时钟源呢? STM32本身十分复杂,外设非常多 但我们实际使用的时候只会用到有限的几个外设,使用任何外设都需要时钟才能启动,但并不是所有的外设都需要系统时钟那么高的频率,为了兼容不同速度的设备,有些高速,有些低速,如果都用高速时钟,势必造成浪费 并且,同一个电路,时钟越快功耗越快,同时抗电磁干扰能力也就越弱,所以较为复杂的
[单片机]
【<font color='red'>STM32</font>】系统时钟RCC详解(超详细,超全面)
stm32_timer基本定时器配置及实现灯闪烁
STM32中一共有11个定时器,其中2个高级控制定时器,4个普通定时器和2个基本定时器,以及2个看门狗定时器和1个系统嘀嗒定时器。 TIM1和TIM8是能够产生3对PWM互补输出的高级登时其,常用于三相电机的驱动,时钟由APB2的输出产生;TIM2-TIM5是普通定时器;TIM6和TIM7是基本定时器,其时钟由APB1输出产生; 本实验要实现的功能是:用普通定时器TIM2每一秒发生一次更新事件,进入中断服务程序翻转LED1的状态。 预备知识: ① STM32通用定时器TIM2是16位自动重装载计数器。 ② 向上计数模式:从0开始计数,计到自动装载寄存器(TIMx_ARR)中的数值时,清0,依次循环。 需要弄清楚的两
[单片机]
stm32_timer基本定时器配置及实现灯闪烁
USART(STM32
USART / USRT 串口模式实现有三种 阻塞模式 / 普通模式:在主函数中接收函数 非阻塞模式 / 中断模式:产生的不影响主程序运行 DMA模式:与主函数互不影响,独立运行 我的理解:阻塞就是死等,非阻塞就是中断 阻塞模式就像是一个延时函数,当这个函数没处理完那么,所有的按照流程需要执行的代码都不会被执行,要等到这个延时完成,类似 平时看书上写的LED灯闪烁,用的delay()一样… 而非阻塞模式就像他定义的那样,一般用的是中断,执行这条语句的时候,开启相应的中断达到一定的条件才进行处理,这样不会影响到流程的执行. STM32中的F0和F1的AF操作方式是不一样的。F0是复用,F1是备用。 据《STM32中文参考
[单片机]
USART(<font color='red'>STM32</font>)
【STM库应用】stm32 之 USART
STM库是官方提供的,其已经做好了底层驱动的配置,用起来是相当简单的;我们只需要了解其每个函数的功能,已经每个函数所使用流程即可! 整个框架就是下面这幅图,我们只需在顶层做调用即可,跟现在做app的差不多! 注:摘自野火,希望大哥不要说我盗版 刚刚开始拿道库,一看这么多函数,感觉有点棘手,无从下手;多亏stm官方也针对该库提供了一个应用手册,画了两天时间进行了探索和实践,发现了一点比较方便的诀窍。 在此给大家分享分享,我们就拿今天的USART来说吧! 至于建工程,网上以及教程里面是非常多的,我也就不多说了! 任意一个外设都对应一个ppp.c和ppp.h文件,所以我们其实也不是无章可循的!同时,stm库他有一
[单片机]
【STM库应用】<font color='red'>stm32</font> 之 USART
STM32 USART串口DMA 接收和发送的源码详解
硬件平台:STM32F103ZET6; 开发环境:KEIL 4; 先说说应用通讯模式,串口终端的工作方式和迪文屏差不多,终端被动接受MCU发的指令,终端会偶尔主动发送一些数据给MCU(像迪文屏的触摸信息上传)。 串口DMA发送: 发送数据的流程: 前台程序中有数据要发送,则需要做如下几件事 1.在数据发送缓冲区内放好要发送的数据,说明:此数据缓冲区的首地址必须要在DMA初始化的时候写入到DMA配置中去。 2.将数据缓冲区内要发送的数据字节数赋值给发送DMA通道,(串口发送DMA和串口接收DAM不是同一个DMA通道) 3.开启DMA,一旦开启,则DMA开始发送数据,说明一下:在KEIL调试好的时候,D
[单片机]
ST最新开发工具为了解基于STM32 ARM Cortex-M3 MCU开方便之门
完整的低成本的评估开发工具通过图形界面探索微控制器的性能和功能 中国,2007年11月6日 — 意法半导体(纽约证券交易所:STM)今天公布了一个价格非常低廉的微控制器开发套件STM32 PerformanceStick,这套开发工具是近日推出的基于ARM Cortex-M3内核的STM32系列微控制器的配套产品。ST设计这套紧凑的开发工具是为了便于用户了解新微控制器的功能和性能,特别值得一提的是,用户可以通过一个图形界面查看微控制器在不同条件下的性能特性。为了鼓励和帮助设计工程师修改和重新编写应用程序源代码,工具包还含有示例应用软件和一套完整的Hitex软件工具。 STM32 PerformanceStick是一套功能完整
[焦点新闻]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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