目录

1. EXTI 是什么?

2. EXTI主要特性

3. EXTI框图

3.1 外部中断/事件线映射

4. EXTI寄存器

4.1 中断屏蔽寄存器 EXTI_IMR

4.2 事件屏蔽寄存器 EXTI_EMR

4.3 上升沿触发选择寄存器 EXTI_RTSR

4.4 下降沿触发选择寄存器 EXTI_FTSR

4.5 软件中断事件寄存器 EXTI_SWIER

4.6 挂起寄存器 EXTI_PR

5. 库函数配置外部中断的步骤

6. STM32外部中断程序

6.1 main.c

6.2 exti.c

6.3 exti.h


1. EXTI 是什么?

        EXTI:外部中断/事件控制器包含多达23个用于产生事件/中断请求边沿检测器。每根输入线都可以单独进行配置,以选择类型 (中断或事件) 和相应的触发事件(上升沿触发、下降沿触发或边沿触发)。每根输入线还可以单独屏蔽。挂起寄存器用于保持中断请求的状态线。是用来专门的管理所有的GPIO用来处理中断和事件的。

        中断的意思就是程序在执行过程中,中断就如同一个小插曲,中断或者事件一来,优先执行中断事件,完成中断以后,再执行未完成的程序。(举个简单的例子就是:打比方我们正在家里学习,学习的同时可能你在开水,这个时候,突然门铃响了,门铃响就是一个中断,这个时候就打断了你正在执行的事(学习),你需要先去开门,看一下是否有重要的事;倘若没有很重要的事(处理完中断事件了),你回到座位上重新开始学习;这个时候突然水壶响了,同样水壶响了也是一个中断,需要再一次打断你正在学习的状态,去关一下水壶(再次去处理中断事件);

2. EXTI主要特性

1. 每个中断/事件线上都具有独立的触发和屏蔽。

2. 每个中断线都具有专用的状态位。

3. 支持多达23个软件事件/中断请求。

4. 检测脉冲宽度低于APB2时钟宽度的外部信号。

3. EXTI框图

要产生中断,必须先配置好并使能中断线。根据需要的边沿检测设置2个触发寄存器,同时在中断屏蔽寄存器的相应位写 1 使能中断请求。当外部中断线上出现选定信号沿时,便会产生中断请求,对应的挂起位会置1。在挂起寄存器的对应位写 1 ,将清除该中断请求。

要产生事件,必须先配置好并使能事件线。根据需要的边沿检测设置2个触发寄存器,同时在事件屏蔽寄存器的相应位写 1 允许事件请求。当事件线上出现选定信号沿时,便会产生事件脉冲,对应的挂起位不会置 1。

通过在软件中对软件中断/事件寄存器写 1 ,也可以产生中断/事件请求。

3.1 外部中断/事件线映射

注意:一个中断线可以控制8个IO口的输入

        void EXTI0_IRQHandler(void)是外部中断0的服务函数,负责WK_UP按键的中断检测;    因为原理图上KEY_UP接引脚PA0

        void EXTI2_IRQHandler(void)是外部中断2的服务函数,负责KEY2按键的中断检测;        因为原理图上KEY2接引脚PE2

        void EXTI3_IRQHandler(void)是外部中断3的服务函数,负责KEY1按键的中断检测;        因为原理图上KEY1接引脚PE3

        void EXTI4_IRQHandler(void)是外部中断4的服务函数,负责KEY0按键的中断检测;        因为原理图上KEY0接引脚PE4

在对上述的理解上需要基于上述图,外部EXTI0是控制PA0/PB0/PC0/PD0/PE0/PF0……  ;简单理解就是EXTI1控制PA1/PB1/PC1/PD1/PE1/PF1…… ; 因此,KEY_UP负责外部中断0的中断服务函数的检测,KEY2负责外部中断2的服务函数的中断检测,KEY1负责外部中断3的服务函数的中断检测,KEY0负责外部中断4的服务函数的中断检测;

4. EXTI寄存器

4.1 中断屏蔽寄存器 EXTI_IMR

中断屏蔽寄存器:EXTI_IMR(Interrupt mask register) 32位寄存器

位31:23  保留,必须保持复位值

位22:0  MRx :x线上的中断屏蔽

                        0:屏蔽来自于x线上的中断请求

                        1:开放来自于x线上的中断请求

4.2 事件屏蔽寄存器 EXTI_EMR

事件屏蔽寄存器 EXTI_EMR(Event mask register) 32位寄存器

位31:23  保留,必须保持复位值

位22:0   MRx:x线上的事件屏蔽

                        0:屏蔽来自x线的事件请求

                        1:开放来自x线的事件请求

4.3 上升沿触发选择寄存器 EXTI_RTSR

上升沿触发选择寄存器 EXIT_RTSR(Rising trigger selection register) 32位寄存器

位31:23 保留,必须保持复位值

位22:0 TRx:线x的上升沿触发事件配置位

                        0:禁止输入线上升沿触发

                        1:允许输入线上升沿触发

4.4 下降沿触发选择寄存器 EXTI_FTSR

下降沿触发选择寄存器 EXIT_RTSR(Falling trigger selection register) 32位寄存器

位31:23 保留,必须保持复位值

位22:0 TRx:线x的下降沿触发事件配置位

                        0:禁止输入线下降沿触发

                        1:允许输入线下降沿触发

4.5 软件中断事件寄存器 EXTI_SWIER

软件中断事件寄存器 EXTI_SWIER(Software interrupt event register)

位 31:23 保留,必须保持复位值。

位 22:0 SWIERx:线 x 上的软件中断 (Software Interrupt on line x)

当该位为“0”时,写“1”将设置 EXTI_PR 中相应的挂起位。如果在 EXTI_IMR 和 EXTI_EMR 中允许产生该中断,则产生中断请求。

通过清除 EXTI_PR 的对应位(写入“1”),可以清除该位为“0”。 

4.6 挂起寄存器 EXTI_PR

挂起寄存器 EXTI_PR(Pending register)

位 31:23 保留,必须保持复位值。

位 22:0 PRx:挂起位 (Pending bit)

                0:没有发生触发请求

                1:发生了选择的触发请求  当在外部中断线上发生了选择的边沿事件,该位被置“1”。

在此位中写入“1”可以清除它,也可以通过改变边沿检测的极性清除。

5. 库函数配置外部中断的步骤

STM32F4的每个IO口都可以作为外部中断的中断输入口,这点也是STM32F4的强大之处(相比于51只有5个中断,2个外部中断、2个定时器中断、1个串口中断)STM32F4的中断控制器支持22个外部中断/事件请求。每个中断都有状态位,每个中断/事件都有独立的触发和屏蔽设置。

STM32F4的22个外部中断为:

EXTI线0-15对应外部IO口的输入中断

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唤醒事件。

库函数配置外部中断的步骤:

1. 使能IO口时钟,初始化IO口为输入

2. 开启SYSCFG时钟,设置IO口与中断线的映射关系;

注意:只要使用到外部中断,必须使能SYSCFG时钟。

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

        配置GPIO与中断线的映射关系函数:

        void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex); 

        ag.    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); 将中断线0 与GPIOA映射起来,那么GPIOA.0与EXTI 1中断线连接了。

3. 初始化线上中断,设置触发条件

初始化是通过EXTI_Init();来实现的;中断线4上的下降沿触发配置如下:

        EXTI_InitTypeDef EXTI_InitStructure;//设置EXTI结构体结构体变量

        EXTI_InitStructure.EXTI_Line=EXTI_Line4; //中断线标号,配置某个中断线上的中断函数,取值范围:EXTI_Line0~EXTI_Line15

EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; //中断模式,选值:中断EXTI_Mode_Interrupt和事件EXTI_Mode_Event

        EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//触发方式,可以是下降沿触发EXTI_Trigger_Falling,上升沿触发                EXTI_Trigger_Rising,或者任意电平(上升沿和下降沿)触发EXTI_Trigger_Rising_Falling

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

        EXTI_Init(&EXTI_InitStructure);  //初始化外设EXTI寄存器

4. 配置好中断分组NVIC,并且使能中断

设置中断线2的中断优先级如下:

        NVIC_InitTypeDef NVIC_InitStructure; //设置NVIC结构体变量

        NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能按键外部中断通道

        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2

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

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

        NVIC_Init(&NVIC_InitStructure); //中断优先级分组初始化

5. 编写中断服务函数

STM32F4的IO口外部中断函数只有7个:

        EXPORT EXTI0_IRQHandler   // 中断线0-4每个中断线对应一个中断函数

        EXPORT EXTI1_IRQHandler

        EXPORT EXTI2_IRQHandler

        EXPORT EXTI3_IRQHandler  

        EXPORT EXTI4_IRQHandler  

        EXPORT EXTI9_5_IRQHandler // 中断线5-9共用中断函数EXPORT EXTI9_5_IRQHandler

        EXPORT EXTI15_10_IRQHandler // 中断线10-15共用EXPORT EXTI15_10_IRQHandler

注意:一个中断线可以控制8个IO口的输入

        void EXTI0_IRQHandler(void)是外部中断0的服务函数,负责WK_UP按键的中断检测;    因为原理图上KEY_UP接引脚PA0

        void EXTI2_IRQHandler(void)是外部中断2的服务函数,负责KEY2按键的中断检测;        因为原理图上KEY2接引脚PE2

        void EXTI3_IRQHandler(void)是外部中断3的服务函数,负责KEY1按键的中断检测;        因为原理图上KEY1接引脚PE3

        void EXTI4_IRQHandler(void)是外部中断4的服务函数,负责KEY0按键的中断检测;        因为原理图上KEY0接引脚PE4

编写中断服务函数时经常使用到的函数:

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);// 判断某个中断是否发生(标志位是否置位)

        void EXTI_ClearITPendingBit(uint32_t EXTI_Line);// 清除中断标志位

void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3)!=RESET)//判断某个线上的中断是否发生
{ …中断逻辑…
EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE上的中断标志位
}
}

6. STM32外部中断程序

本程序主要实现:通过中断来检测按键:

按下KEY_UP控制蜂鸣器,一叫一停;KEY2控制DS0,一亮一灭;KEY1控制DS1,一亮一灭;KEY0同时控制DS0和DS1,状态翻转;

6.1 main.c

#include "stm32f4xx.h"
#include "delay.h"
#include "LED.h"
#include "BEEP.h"
#include "Key.h"
#include "usart.h"
#include "exti.h"int main()
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组delay_init(168); //初始化延迟函数uart_init(115200); //初始化串口,设置波特率115200LED_Init(); //初始化LEDBEEP_Init(); //初始化蜂鸣器EXTIX_Init(); //初始化外部中断LED0=0; //LED0点亮while(1){printf("OK\r\n");//通过串口发送ok    这里需要注意想要通过串口打印必须引用头文件#include "usart.h"
//更加简单干脆的说:想要使用printf函数,就必须引用该头文件,否则就会报错delay_ms(1000);//1秒发送一次}
}

6.2 exti.c

#include "delay.h"
#include "Key.h"
#include "BEEP.h"
#include "LED.h"
#include "exti.h"void EXTI0_IRQHandler(void)  //外部中断线0中断服务函数
{delay_ms(10);  //消抖if(KEY_UP==1)  //KEY_UP=1 表示按下{BEEP=!BEEP; //蜂鸣器翻转 }         EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位
}
void EXTI2_IRQHandler(void)//中断线2的外部中断服务函数
{delay_ms(10); //按键消抖if(KEY2==0)//KEY2按下{LED0=!LED0;//LED0翻转}EXTI_ClearITPendingBit(EXTI_Line2);//消除中断线2上的中断标志位
}
void EXTI3_IRQHandler(void)//中断线3的外部中断服务函数
{delay_ms(10);//按键消抖if(KEY1==0)//KEY1按下{LED1=!LED1;//LED1翻转}EXTI_ClearITPendingBit(EXTI_Line3);//消除中断线3上的中断标志位
}
void EXTI4_IRQHandler(void)//中断线4的外部中断服务函数
{delay_ms(10);//按键消抖if(KEY0==0)//KEY0按下{LED0=!LED0;//LED0翻转LED1=!LED1;//LED1翻转}EXTI_ClearITPendingBit(EXTI_Line4);//消除中断线4上的中断标志位
}
void EXTIX_Init(void)
{NVIC_InitTypeDef NVIC_InitStructure;// 设置中断优先级结构体变量EXTI_InitTypeDef EXTI_InitStructure;//设置外部中断结构体结构体变量Key_Init(); //按键对应的IO口初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE); //使能SYSCFG时钟SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0); //PA0连接中断线0,映射按键KEY_UP   简单来说 接下来四条语句实现把引脚接在对应的中断线上,类似于复用功能SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource2); //PE2连接中断线2,映射按键KEY2SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource3); //PE3连接中断线3,映射按键KEY1SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource4); //PE4连接中断线4,映射按键KEY0//以下之所以要分开设置EXTI初始化函数,是因为KEY_UP是高电平1有效,KEY0/KEY1/KEY2是低电平0有效,//所以上升沿和下降沿需要分开设置EXTI_InitStructure.EXTI_Line=EXTI_Line0;//中断线0EXTI_InitStructure.EXTI_LineCmd=ENABLE;//中断使能EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//模式中断EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;//上升沿有效 通过原理图可以发现KEY_UP按键左侧接V3.3,右侧接引脚,按键没有按下时,引脚呈现低电平,按键一旦按下,引脚呈现高电平,按键按下也就表示着上升沿有效EXTI_Init(&EXTI_InitStructure);//初始化外部中断EXTI_InitStructure.EXTI_Line=EXTI_Line2 | EXTI_Line3 | EXTI_Line4;//中断线2/3/4EXTI_InitStructure.EXTI_LineCmd=ENABLE;//中断使能EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//模式中断EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//下降沿  原理图上KEY0/KEY1/KEY2左侧接地,按键一旦按下,表示引脚低电平,也就是下降沿有效EXTI_Init(&EXTI_InitStructure);//初始化外部中断NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;//外部中断0NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能外部中断0NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x00;//抢占优先级0NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x02;//响应优先级2NVIC_Init(&NVIC_InitStructure);//初始化中断优先级NVIC_InitStructure.NVIC_IRQChannel=EXTI2_IRQn;//外部中断2NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能外部中断2NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x03;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x02;//响应优先级2NVIC_Init(&NVIC_InitStructure);//初始化中断优先级NVIC_InitStructure.NVIC_IRQChannel=EXTI3_IRQn;//外部中断3NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能外部中断3NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02;//抢占优先级2NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x02;//响应优先级2NVIC_Init(&NVIC_InitStructure);//初始化中断优先级NVIC_InitStructure.NVIC_IRQChannel=EXTI4_IRQn;//外部中断4NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能外部中断4NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;//抢占优先级1NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x02;//响应优先级2NVIC_Init(&NVIC_InitStructure);//初始化中断优先级
}// 这里和51的外部中断的优先级顺序是相同的,抢占优先级等级越低

6.3 exti.h

#ifndef _EXTI__H_
#define _EXTI__H_void EXTIX_Init(void);#endif

STM32F4_外部中断详解(EXTI)相关推荐

  1. STM32开发 -- 外部中断详解

    如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/87376865 在讲三轴加速度计的时候,提到外部中断.接下来就看看中断为什么这 ...

  2. 【STM32学习笔记】(13)——外部中断详解

    EXTI 简介         EXTI(External interrupt/event controller)-外部中断/事件控制器,管理了控制器的 20 个中断/事件线.每个输入线可以独立地配置 ...

  3. STM32 外部中断详解(原理+配置代码)

    本文介绍了STM32基于标准外设库的外部中断配置,以及基于参考手册如何更加寄存器配置外部中断 文章目录 1 前言 2 STM32的外部中断 3 中断服务函数的映射关系 4 外部中断的配置 5 寄存器的 ...

  4. STM32入门笔记03_EXTI外部中断详解+案例:红外对射计数、旋转编码器计数

    EXTI外部中断 中断的相关概念 中断源: 可以引起中断的事件称为中断源 中断: 在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成 ...

  5. 单片机中段程序_单片机外部中断详解及程序

    单片机在自主运行的时候一般是在执行一个死循环程序,在没有外界干扰(输入信号)的时候它基本处于一个封闭状态.比如一个电子时钟,它会按时.分.秒的规律来自主运行并通过输出设备(如液晶显示屏)把时间显示出来 ...

  6. STM32 中断详解

    目录 1 EXTI控制器 2 NVIC控制器 3 code 中断,在单片机中占有非常重要的地位.代码默认地从上向下执行,遇到条件或者其他语句,会按照指定的地方跳转.而在单片机执行代码的过程中,难免会有 ...

  7. linux内核中断详解

    linux内核中断详解 1.中断的硬件触发流程 外设:如果外设有操作或者有数据可用,那么就会产生一个电信号,这个电信号发送给中断控制器. 中断控制器:中断控制器接收到外设发来的电信号以后,进行进一步的 ...

  8. 51单片机中断详解(上)

    一.中断的概念 中断发生 CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理 中断响应和中断服务 CPU暂时中断当前的工作,转去处理事件B 中断返回 待CPU将事件B处理完毕后,再回到原来 ...

  9. 【stm32】中断详解

    stm32中断的顺序: 1)初始化 IO 口. 2)开启 AFIO 时钟 3)EXTI配置. 4)NVIC配置. 5)编写中断服务函数. 1 NVIC中断优先级管理 CM3 内核支持 256 个中断, ...

最新文章

  1. AJAX 传值数据类型问题
  2. Android判断Service是否运行
  3. 【Java数据结构】自己实现一个HahMap(实现其put, toString, get方法)
  4. php访问者信息,如何通过PHP检索访问者的ISP?
  5. ElasticSearch 动态映射与静态映射_08
  6. 多个python文件打包成exe_Python 3.4 .py文件打包成exe可执行文件方法
  7. mysql not exists优化_MySQL优化--NOT EXISTS和LEFT JOIN方式差异
  8. 20145209 《信息安全系统设计基础》第10周学习总结
  9. Nginx默认虚拟主机、 Nginx用户认证、Nginx域名重定向、访问日志·····
  10. C/C++与lua实现互调
  11. Socket.IO文档(1)
  12. 网管必读-常用网络命令
  13. tomcat 如何进行优化?优化方案有哪些?
  14. win10 ie浏览器安装Flash Player Debugger解决方案
  15. Battleship!
  16. 需要查询前一次该厂商,料号的单价, 这个sql语句很难写,你碰到过没有
  17. 【二次分配问题】基于遗传算法 (GA)、粒子群优化 (PSO) 和萤火虫算法 (FA) 求解二次分配( QAP)问题(MATLAB 实现)
  18. 金蝶cloud 常用数据库表
  19. linux time效率,time(),gettimeofday()及GetTickCount()效率比较
  20. sql 语句操作,修改字段中字符串的一部分

热门文章

  1. 滤波算法、中值和均值滤波区别
  2. 【计算机组成原理-chapter1】计算机组成原理概述
  3. Comparator--比较器
  4. WPF中的StackPanel、WrapPanel、DockPanel
  5. Shell Tools and Scripting
  6. Mac端口5000被ControlCe占用问题解决方法
  7. 《Code Complete》之个人性格
  8. 【第24篇】YOLOR:多任务的统一网络
  9. Vue2积分商城PC端项目(六)
  10. ntp VS chrony