第17章 EXTI—外部中断/事件控制器

上一章节我们已经详细介绍了NVIC,对STM32F7xx中断管理系统有个全局的了解,我们这章的内容是NVIC的实例应用,也是STM32F7xx控制器非常重要的一个资源。学习本章时,配合《STM32F76xxx参考手册》系统配置控制器以及中断和事件章节一起阅读,效果会更佳,特别是涉及到寄存器说明的部分。

特别说明,本书内容是以STM32F767xx系列控制器资源讲解。

17.1  EXTI简介

外部中断/事件控制器(EXTI)管理了控制器的25个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。

17.2  EXTI功能框图

EXTI的功能框图包含了EXTI最核心内容,掌握了功能框图,对EXTI就有一个整体的把握,在编程时就思路就非常清晰。EXTI功能框图见图 17-1。

图 17-1 EXTI功能框图

EXTI可分为两大部分功能,一个是产生中断,另一个是产生事件,这两个功能从硬件上就有所不同。

首先我们来看图 171中红色虚线指示的电路流程。它是一个产生中断的线路,最终信号流入到NVIC控制器内。

编号1是输入线,EXTI控制器有25个中断/事件输入线,这些输入线可以通过寄存器设置为任意一个GPIO,也可以是一些外设的事件,这部分内容我们将在后面专门讲解。输入线一般是存在电平变化的信号。

编号2是一个边沿检测电路,它会根据上升沿触发选择寄存器(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR)对应位的设置来控制信号触发。边沿检测电路以输入线作为信号输入端,如果检测到有边沿跳变就输出有效信号1给编号3电路,否则输出无效信号0。而EXTI_RTSR和EXTI_FTSR两个寄存器可以控制器需要检测哪些类型的电平跳变过程,可以是只有上升沿触发、只有下降沿触发或者上升沿和下降沿都触发。

编号3电路实际就是一个或门电路,它一个输入来自编号2电路,另外一输入来自软件中断事件寄存器(EXTI_SWIER)。EXTI_SWIER允许我们通过程序控制就可以启动中断/事件线,这在某些地方非常有用。我们知道或门的作用就是有1就为1,所以这两个输入随便一个有有效信号1就可以输出1给编号4和编号6电路。

编号4电路是一个与门电路,它一个输入编号3电路,另外一个输入来自中断屏蔽寄存器(EXTI_IMR)。与门电路要求输入都为1才输出1,导致的结果如果EXTI_IMR设置为0时,那不管编号3电路的输出信号是1还是0,最终编号4电路输出的信号都为0;如果EXTI_IMR设置为1时,最终编号4电路输出的信号才由编号3电路的输出信号决定,这样我们可以简单的控制EXTI_IMR来实现是否产生中断的目的。编号4电路输出的信号会被保存到挂起寄存器(EXTI_PR)内,如果确定编号4电路输出为1就会把EXTI_PR对应位置1。

编号5是将EXTI_PR寄存器内容输出到NVIC内,从而实现系统中断事件控制。

接下来我们来看看绿色虚线指示的电路流程。它是一个产生事件的线路,最终输出一个脉冲信号。

产生事件线路是在编号3电路之后与中断线路有所不同,之前电路都是共用的。编号6电路是一个与门,它一个输入编号3电路,另外一个输入来自事件屏蔽寄存器(EXTI_EMR)。如果EXTI_EMR设置为0时,那不管编号3电路的输出信号是1还是0,最终编号6电路输出的信号都为0;如果EXTI_EMR设置为1时,最终编号6电路输出的信号才由编号3电路的输出信号决定,这样我们可以简单的控制EXTI_EMR来实现是否产生事件的目的。

编号7是一个脉冲发生器电路,当它的输入端,即编号6电路的输出端,是一个有效信号1时就会产生一个脉冲;如果输入端是无效信号就不会输出脉冲。

编号8是一个脉冲信号,就是产生事件的线路最终的产物,这个脉冲信号可以给其他外设电路使用,比如定时器TIM、模拟数字转换器ADC等等。

产生中断线路目的是把输入信号输入到NVIC,进一步会运行中断服务函数,实现功能,这样是软件级的。而产生事件线路目的就是传输一个脉冲信号给其他外设使用,并且是电路级别的信号传输,属于硬件级的。

另外,EXTI是在APB2总线上的,在编程时候需要注意到这点。

17.3  中断/事件线

EXTI有25个中断/事件线,每个GPIO都可以被设置为输入线,占用EXTI0至EXTI15,还有另外七根用于特定的外设事件,见表 17-1。

七根特定外设中断/事件线由外设触发,具体用法参考《STM32F4xx中文参考手册》中对外设的具体说明。

表 17-1 EXTI中断/事件线


中断/事件线


输入源


EXTI0


PX0(X可为A,B,C,D,E,F,G,H,I)


EXTI1


PX1(X可为A,B,C,D,E,F,G,H,I)


EXTI2


PX2(X可为A,B,C,D,E,F,G,H,I)


EXTI3


PX3(X可为A,B,C,D,E,F,G,H,I)


EXTI4


PX4(X可为A,B,C,D,E,F,G,H,I)


EXTI5


PX5(X可为A,B,C,D,E,F,G,H,I)


EXTI6


PX6(X可为A,B,C,D,E,F,G,H,I)


EXTI7


PX7(X可为A,B,C,D,E,F,G,H,I)


EXTI8


PX8(X可为A,B,C,D,E,F,G,H,I)


EXTI9


PX9(X可为A,B,C,D,E,F,G,H,I)


EXTI10


PX10(X可为A,B,C,D,E,F,G,H,I)


EXTI11


PX11(X可为A,B,C,D,E,F,G,H,I)


EXTI12


PX12(X可为A,B,C,D,E,F,G,H,I)


EXTI13


PX13(X可为A,B,C,D,E,F,G,H,I)


EXTI14


PX14(X可为A,B,C,D,E,F,G,H,I)


EXTI15


PX15(X可为A,B,C,D,E,F,G,H)


EXTI16


可编程电压检测器(PVD)输出


EXTI17


RTC闹钟事件


EXTI18


USB OTG FS唤醒事件


EXTI19


以太网唤醒事件


EXTI20


USB OTG HS(在FS中配置)唤醒事件


EXTI21


RTC入侵和时间戳事件


EXTI22


RTC唤醒事件


EXTI23


LPTIM1 异步事件


EXTI24


MDIO Slave 异步事件

EXTI0至EXTI15用于GPIO,通过编程控制可以实现任意一个GPIO作为EXTI的输入源。由表 171可知,EXTI0可以通过SYSCFG外部中断配置寄存器1(SYSCFG_EXTICR1)的EXTI0[3:0]位选择配置为PA0、PB0、PC0、PD0、PE0、PF0、PG0、PH0或者PI0,见图 172。其他EXTI线(EXTI中断/事件线)使用配置都是类似的。

图 17-2 EXTI0输入源选择

17.4  EXTI初始化详解

HAL库函数的EXIT初始化非常简单,只需配置好IO口的模式,然后配置中断源、中断优先级、使能中断。

1) HAL_NVIC_SetPriority:该函数负责EXTI中断/事件线选择,可选EXTI0至EXTI25,可参考表 171选择,配置优先级。

2) HAL_NVIC_EnableIRQ:该函数负责控制使能中断。

17.5  外部中断控制实验

中断在嵌入式应用中占有非常重要的地位,几乎每个控制器都有中断功能。中断对保证紧急事件得到第一时间处理是非常重要的

我们设计使用外接的按键来作为触发源,使得控制器产生中断,并在中断服务函数中实现控制RGB彩灯的任务。17.5.1  硬件设计轻触按键在按下时会使得引脚接通,通过电路设计可以使得按下时产生电平变化,见17-3

图 17-3 按键电路设计

17.5.2  软件设计

这里只讲解核心的部分代码,有些变量的设置,头文件的包含等并没有涉及到,完整的代码请参考本章配套的工程。我们创建了两个文件:bsp_exti.c和bsp_exti.h文件用来存放EXTI驱动程序及相关宏定义,中断服务函数放在stm32f7xx_it.c文件中。

1. 编程要点

1) 初始化系统时钟;

2) 初始化RGB彩灯的GPIO;

3) 开启按键GPIO时钟;

4) 配置NVIC;

5) 配置按键GPIO为输入模式;

6) 将按键GPIO连接到EXTI源输入;

7) 配置按键EXTI中断/事件线;

8) 编写EXTI中断服务函数。

2. 软件分析
按键和EXTI宏定义

代码清单 171  按键和EXTI 宏定义

1 #define KEY1_INT_GPIO_PORT                GPIOA
 2 #define KEY1_INT_GPIO_CLK_ENABLE()        __GPIOA_CLK_ENABLE();
 3 #define KEY1_INT_GPIO_PIN                 GPIO_PIN_0
 4 #define KEY1_INT_EXTI_IRQ                 EXTI0_IRQn
 5 #define KEY1_IRQHandler                   EXTI0_IRQHandler
 6
 7 #define KEY2_INT_GPIO_PORT                GPIOC
 8 #define KEY2_INT_GPIO_CLK_ENABLE()        __GPIOA_CLK_ENABLE();
 9 #define KEY2_INT_GPIO_PIN                 GPIO_PIN_13
10 #define KEY2_INT_EXTI_IRQ                 EXTI15_10_IRQn
11 #define KEY2_IRQHandler                   EXTI15_10_IRQHandler

使用宏定义方法指定与电路设计相关配置,这对于程序移植或升级非常有用的。

EXTI中断配置

代码清单 172  EXTI中断配置

1 void EXTI_Key_Config(void)
 2 {
 3     GPIO_InitTypeDef GPIO_InitStructure;
 4
 5     /*开启按键GPIO口的时钟*/
 6     KEY1_INT_GPIO_CLK_ENABLE();
 7     KEY2_INT_GPIO_CLK_ENABLE();
 8
 9     /* 选择按键1的引脚 */
10     GPIO_InitStructure.Pin = KEY1_INT_GPIO_PIN;
11     /* 设置引脚为输入模式 */
12     GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
13     /* 设置引脚不上拉也不下拉 */
14     GPIO_InitStructure.Pull = GPIO_NOPULL;
15     /* 使用上面的结构体初始化按键 */
16     HAL_GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
17     /* 配置 EXTI 中断源 到key1 引脚、配置中断优先级*/
18     HAL_NVIC_SetPriority(KEY1_INT_EXTI_IRQ, 0, 0);
19     /* 使能中断 */
20     HAL_NVIC_EnableIRQ(KEY1_INT_EXTI_IRQ);
21
22     /* 选择按键2的引脚 */
23     GPIO_InitStructure.Pin = KEY2_INT_GPIO_PIN;
24     /* 其他配置与上面相同 */
25     HAL_GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);
26     /* 配置 EXTI 中断源 到key1 引脚、配置中断优先级*/
27     HAL_NVIC_SetPriority(KEY2_INT_EXTI_IRQ, 0, 0);
28     /* 使能中断 */
29     HAL_NVIC_EnableIRQ(KEY2_INT_EXTI_IRQ);
30 }

首先,使用GPIO_InitTypeDef结构体定义用于GPIO初始化配置的变量,关于这个结构体前面都已经做了详细的讲解。

使用GPIO之前必须开启GPIO端口的时钟;

调用HAL_NVIC_SetPriority和HAL_NVIC_EnableIRQ函数完成对按键1、按键2优先级配置并使能中断通道。

作为中断/时间输入线把GPIO配置为中断上升沿触发模式,这里不使用上拉或下拉,有外部电路完全决定引脚的状态。

我们的目的是产生中断,执行中断服务函数,EXTI选择中断模式,按键1使用下降沿触发方式,并使能EXTI线。

按键2基本上采用与按键1相关参数配置,只是改为上升沿触发方式。

EXTI中断服务函数

代码清单 17-3  EXTI中断服务函数

1 void KEY1_IRQHandler(void)
 2 {
 3     //确保是否产生了EXTI Line中断
 4     if (__HAL_GPIO_EXTI_GET_IT(KEY1_INT_GPIO_PIN) != RESET) {
 5         // LED1 取反
 6         LED1_TOGGLE;
 7         //清除中断标志位
 8         __HAL_GPIO_EXTI_CLEAR_IT(KEY1_INT_GPIO_PIN);
 9     }
10 }
11
12 void KEY2_IRQHandler(void)
13 {
14     //确保是否产生了EXTI Line中断
15     if (__HAL_GPIO_EXTI_GET_IT(KEY2_INT_GPIO_PIN) != RESET) {
16         // LED2 取反
17         LED2_TOGGLE;
18         //清除中断标志位
19         __HAL_GPIO_EXTI_CLEAR_IT(KEY2_INT_GPIO_PIN);
20     }
21 }

当中断发生时,对应的中断服务函数就会被执行,我们可以在中断服务函数实现一些控制。

一般为确保中断确实发生,我们会在中断服务函数调用中断标志位状态读取函数读取外设中断标志位并判断标志位状态。

__HAL_GPIO_EXTI_GET_IT函数用来获取EXTI的中断标志位状态,如果EXTI线有中断发生函数返回“SET”否则返回“RESET”。实际上,__HAL_GPIO_EXTI_GET_IT函数是通过读取EXTI_PR寄存器值来判断EXTI线状态的。

按键1的中断服务函数我们让LED1翻转其状态,按键2的中断服务函数我们让LED2翻转其状态。执行任务后需要调用__HAL_GPIO_EXTI_CLEAR_IT函数清除EXTI线的中断标志位。

主函数

代码清单 17-4 主函数

1 int main(void)
 2 {
 3     /* 系统时钟初始化成216 MHz */
 4     SystemClock_Config();
 5     /* LED 端口初始化 */
 6     LED_GPIO_Config();
 7
 8     /* 初始化EXTI中断,按下按键会触发中断,
 9     *  触发中断会进入stm32f7xx_it.c文件中的函数
10     *
11     KEY1_IRQHandler和KEY2_IRQHandler,处理中断,反转LED灯。
12     */
13     EXTI_Key_Config();
14
15     /* 等待中断,由于使用中断方式,CPU不用轮询按键
16     */
17     while (1) {
18     }
19 }

主函数非常简单,只有三个任务函数。SystemClock_Config 初始化系统时钟,LED_GPIO_Config函数定义在bsp_led.c文件内,完成RGB彩灯的GPIO初始化配置。EXTI_Key_Config函数完成两个按键的GPIO和EXTI配置。

17.5.3  下载验证

保证开发板相关硬件连接正确,把编译好的程序下载到开发板。此时RGB彩色灯是暗的,如果我们按下开发板上的按键1,RGB彩灯变亮,再按下按键1,RGB彩灯又变暗;如果我们按下开发板上的按键2并弹开,RGB彩灯变亮,再按下开发板上的KEY2并弹开,RGB彩灯又变暗。

原文地址:https://www.cnblogs.com/firege/p/9287065.html

时间: 2024-11-07 13:03:10

第17章 EXTI—外部中断/事件控制器的相关文章

《零死角玩转STM32》-17-EXTI外部中断/事件控制器

/* * 本文中的相关图片来自火哥的教程,只作为随笔记录,无侵权之意 * 21:25:46, 2017-04-08 */ EXTI:外部中断/事件控制器.STM32F429共有23根,其中EXTI0~EXTI15,分别对应GPIO中的PX0 ~ PX15,另外7根线有如下用途: (中间省略了EXTI1 ~ EXTI15) EXTI功能框图如下所示: 按照图中的序号标识,可以清晰的看出外部GPIO引脚上的电平变化是如何传递到内核,即GPIO -> EXTI -> NVIC,并触发相应的中断/事件

STM32本学习笔记EXTI(外部中断)

参考资料:STM32数据表.网络信息 =========================================切割线========================================= 外部中断/事件控制器由19个产生事件/中断要求的边沿检測器组成.每一个输入线能够独立地配置 输入类型(脉冲或挂起)和相应的触发事件(上升沿或下降沿或者双边沿都触发).每一个输入线都能够被独 立的屏蔽. 挂起寄存器保持着状态线的中断要求. ==========================

GPIO和外部中断/时间控制器(EXTI)

2.1          GPIO的8种工作模式 GPIO工作图如下: 4种输入模式 结构图的上半部分分为输入模式结构, 分为上拉模式,下拉模式,浮空模式和模拟输入模式. 上/下拉模式:通过设置配置寄存器(CRL,CRH)来控制1和2开关,于是得到GPIO的上拉输入模式(GPIO_Mode_IPU)和下拉输入模式(GPIO_Mode_IPD). 浮空输入模式(GPIO_Mode_IN_FLOATING):没有接上下拉电阻,经由TTL施密特触发器输入. 配置成这个模式直接用电压表测量其引脚电压为1

STM32基本GPIO操作:按键输入(扫描+外部中断)

(涉及专有名词较多,难免解释不到位,若有错误还请指出,谢谢!) 硬件连接图如下: 一.扫描 思路是在main函数中通过死循环来扫描端口电平状态检测,以此判断按键是否按下.实现较为简单. 1.初始化(注意C语言中变量声明需放在函数开头) 以下是初始化PB5端口(LED灯)的代码,每一条语句的含义在我另一篇博客里 GPIO_InitTypeDef GPIO_Init1; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_Init1.

STM32学习笔记(九) 外部中断,待机模式和事件唤醒

学会知识只需要不段的积累和提高,但是如何将知识系统的讲解出来就需要深入的认知和系统的了解.外部中断和事件学习难度并不高,不过涉及到STM32的电源控制部分,还是值得认真了解的,在本文中我将以实际代码为例详细讲解这些内容,希望对每一个阅读者有帮助. 1.外部中断 如果已经学习了SysTick系统时钟滴答实验,掌握了Cortex-M3中断的相关知识,那么外部中断也是比较好理解的,和SysTick中断一样,外部中断也是当有信号触发时,如果中断屏蔽寄存器允许触发,就会产生中断,这时CPU查找中断向量表,

cortex_m3_stm32嵌入式学习笔记(四):外部中断实验

本章学习将STM32的IO口作为外部中断输入(实现和按键扫描一样的功能) STM32 的每个 IO 都可以作为外部中断的中断输入口,这点也是 STM32 的强大之处. STM32F103 的中断控制器支持 19 个外部中断/事件请求.每个中断设有状位,每个中断/事件都有独立的触发和屏蔽设置. STM32F103 的19 个外部中断为: 线 0~15:对应外部 IO 口的输入中断.(本章只学习这一种) 线 16:连接到 PVD 输出. 线 17:连接到 RTC 闹钟事件. 线 18:连接到 USB

STM32F104VG (一)中断与外部中断

一.基础知识 1.ARM的中断优先级分硬件优先级和软件优先级两种 其中软件优先级又由抢占优先级和响应优先级组成 2.中断的优先级采用编号小优先的原则. 3.一般情况: 1).如果设定了软件优先级,先看软件优先级: 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断. 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之

STM32 外部中断简介

文章来源:http://blog.chinaunix.net/uid-24219701-id-4088004.html STM32  IO 口中断的一些基础概念.STM32 的每个 IO 都可以作为外部中断的中断输入口,这点也是 STM32 的强大之处.STM32F103 的中断控制器支持 19 个外部中断/事件请求.每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置.STM32F103 的19 个外部中断为: 线 0~15:对应外部 IO 口的输入中断. 线 16:连接到 PVD 输出

STM32之外部中断控制

一.STM32外部中断 1.STM32外部中断结构图 如上图所示: 主要包括四个环节,GPIO.AFIO.EXTI.NVIC. 2.STM32外部中断软件配置步骤 ① 配置NVIC控制器 ② 使能GPIO和AFIO时钟 ③ 配置GPIO (复用功能的输入输出配置) ④ 配置AFIO (选定要配置为EXTI的I/O口线) ⑤  EXTI控制器的配置 配置寄存器就好像是我们在更改STM32的硬件电路,让它们处于一种新的工作状态--外部中断模式. 二.STM32外部中断软件配置细节 以PA0引脚的外部