1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自《STM32F7 开发指南(HAL 库版)》关注官方微信号公众号,获取更多资料:正点原子

第九章 外部中断实验

这一章,我们将向大家介绍如何使用 STM32F7 的外部输入中断。在前面几章的学习中,

我们掌握了 STM32F7 的 IO 口最基本的操作。本章我们将介绍如何将 STM32F7 的 IO 口作为外

部中断输入,在本章中,我们将以中断的方式,实现我们在第七章所实现的功能。本章分为如

下几个部分:

9.1 STM32F7 外部中断简介

9.2 硬件设计

9.3 软件设计

9.4 下载验证

9.5 STM32CubeMX 配置外部中断

9.1 STM32F7 外部中断简介

STM32F7 的 IO 口在第六章有详细介绍,而中断优先级分组管理在前面也有详细的阐述。

这里我们将介绍 STM32F7 外部 IO 口的中断功能,通过中断的功能,达到第八章实验的效果,

即:通过板载的 4 个按键,控制板载的两个 LED 的亮灭。

这里我们首先讲解 STM32F7 IO 口中断的一些基础概念。STM32F7 的每个 IO 都可以作为

外部中断的中断输入口,这点也是 STM32F7 的强大之处。STM32F7 的中断控制器支持 22 个外

部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。STM32F7

的 23 个外部中断为:

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

EXTI 线 23:连接到 LPTIM1 异步事件。

从上面可以看出,中断线 0-15 对应外部 IO 口的输入中断,一共是 16 个外部中断线。

STM32F7 供 IO 口使用的中断线只有 16 个,但是 STM32F7 的 IO 口却远远不止 16 个,那么

STM32F7 是怎么把 16 个中断线和 IO 口一一对应起来的呢?于是 STM32 就这样设计,GPIO

的引脚 GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G,H,I)分别对应中断线 0~15。这样每个中断线对应

了最多 9 个 IO 口,以线 0 为例:它对应了 GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、

GPIOF.0、GPIOG.0,GPIOH.0,GPIOI.0。而中断线每次只能连接到 1 个 IO 口上,这样就需要通

过配置来决定对应的中断线配置到哪个 GPIO 上了。下面我们看看 GPIO 跟中断线的映射关系

图:

图 9.1.1 GPIO 和中断线的映射关系图

GPIO 和中断线映射关系是在寄存器 SYSCFG_EXTICR1~ SYSCFG_EXTICR4 中配置的。

所以我们要配置外部中断,还需要打开 SYSCFG 时钟。

接下来我们来看看使用 HAL 库配置外部中断的一般步骤。HAL 中外部中断相关配置函数

和定义在文件 stm32f7xx_hal_exti.h 和 stm32f7xx_hal_exti.c 文件中。

1) 使能 IO 口时钟。

首先,我们要使用 IO 口作为中断输入,所以我们要使能相应的 IO 口时钟,具体的操作方

法跟我们按键实验是一致的,这里就不做过多讲解。

2) 设置 IO 口模式,触发条件,开启 SYSCFG 时钟,设置 IO 口与中断线的映射关系。

该步骤如果我们使用标准库那么需要多个函数分部实现。而当我们使用 HAL 库的时候,

则都是在函数 HAL_GPIO_Init 中一次性完成的。例如我们要设置 PA0 链接中断线 0,并且为上

升沿触发,代码为:GPIO_InitTypeDef GPIO_Initure;

GPIO_Initure.Pin=GPIO_PIN_0;

//PA0

GPIO_Initure.Mode=GPIO_MODE_IT_RISING; //外部中断,上升沿触发

GPIO_Initure.Pull=GPIO_PULLDOWN;

//默认下拉

HAL_GPIO_Init(GPIOA,&GPIO_Initure);

当我们调用 HAL_GPIO_Init 设置 IO 的 Mode 值为 GPIO_MODE_IT_RISING(外部中断上

升 沿 触 发 ), GPIO_MODE_IT_FALLING ( 外 部 中 断 下 降 沿 触 发 ) 或 者

GPIO_MODE_IT_RISING_FALLING(外部中断双边沿触发)的时候,该函数内部会通过判断

Mode 的值来开启 SYSCFG 时钟,并且设置 IO 口和中断线的映射关系。

因为我们这里初始化的是 PA0,根据图 9.1.1 可知,调用该函数后中断线 0 会自动连接到

PA0。如果某个时间,我们又同样的方式初始化了 PB0,那么 PA0 与中断线的链接将被清除,

而直接链接 PB0 到中断线 0。

3) 配置中断优先级(NVIC),并使能中断。

我们设置好中断线和 GPIO 映射关系,然后又设置好了中断的触发模式等初始化参数。既

然是外部中断,涉及到中断我们当然还要设置 NVIC 中断优先级。这个在前面已经讲解过,这

里我们就接着上面的范例, 设置中断线 0 的中断优先级并使能外部中断 0 的方法为:

HAL_NVIC_SetPriority(EXTI0_IRQn,2,1); //抢占优先级为 2,子优先级为 1

HAL_NVIC_EnableIRQ(EXTI0_IRQn); //使能中断线 2

上面这段代码相信大家都不陌生,我们在前面的串口实验的时候讲解过,这里不再讲解。

4) 编写中断服务函数。

我们配置完中断优先级之后,接着要做的就是编写中断服务函数。中断服务函数的名字是

在 HAL 库中事先有定义的。这里需要说明一下,STM32F7 的 IO 口外部中断函数只有 7 个,分

别为:

void EXTI0_IRQHandler();

void EXTI1_IRQHandler();

void EXTI2_IRQHandler();

void EXTI3_IRQHandler();

void EXTI4_IRQHandler();

void EXTI9_5_IRQHandler();

void EXTI15_10_IRQHandler();

中断线 0-4 每个中断线对应一个中断函数,中断线 5-9 共用中断函数 EXTI9_5_IRQHandler,中

断线 10-15 共用中断函数 EXTI15_10_IRQHandler。一般情况下,我们可以把中断控制逻辑直接

编写在中断服务函数中,但是 HAL 库把中断处理过程进行了简单封装,请看下面步骤 5 讲解。

5) 编写中断处理回调函数 HAL_GPIO_EXTI_Callback

在使用 HAL 库的时候,我们也可以跟使用标准库一样,在中断服务函数中编写控制逻辑。

但 是 HAL 库 为 了 用 户 使 用 方 便 , 它 提 供 了 一 个 中 断 通 用 入 口 函 数

HAL_GPIO_EXTI_IRQHandler,在该函数内部直接调用回调函数 HAL_GPIO_EXTI_Callback。

我们可以看看 HAL_GPIO_EXTI_IRQHandler 函数定义:

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)

{

if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)

{

__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);

HAL_GPIO_EXTI_Callback(GPIO_Pin);

}

}

该函数实现的作用非常简单,通过入口参数 GPIO_Pin 判断中断来自哪个 IO 口,然后清除

相应的中断标志位,最后调用回调函数 HAL_GPIO_EXTI_Callback()实现控制逻辑。所以我们

编写中断控制逻辑将跟串口实验类似,在所有的外部中断服务函数中直接调用外部中断共用处

理函数 HAL_GPIO_EXTI_IRQHandler,然后在回调函数 HAL_GPIO_EXTI_Callback 中通过判

断中断是来自哪个 IO 口编写相应的中断服务控制逻辑。

讲到这里,相信大家对 STM32 的 IO 口外部中断已经有了一定的了解。下面我们再总结一

下配置 IO 口外部中断的一般步骤:

1)使能 IO 口时钟。

2)调用函数 HAL_GPIO_Init 设置 IO 口模式,触发条件,使能 SYSCFG 时钟以及设置 IO

口与中断线的映射关系。

3)配置中断优先级(NVIC),并使能中断。

4)在中断服务函数中调用外部中断共用入口函数 HAL_GPIO_EXTI_IRQHandler。

5)编写外部中断回调函数 HAL_GPIO_EXTI_Callback 实现控制逻辑。

通过以上几个步骤的设置,我们就可以正常使用外部中断了。

本章,我们要实现同第七章差不多的功能,但是这里我们使用的是中断来检测按键,还是

KEY_UP 控制 DS0,DS1 互斥点亮;KEY2 控制 DS0,按一次亮,再按一次灭;KEY1 控制 DS1,

效果同 KEY2;KEY0 则同时控制 DS0 和 DS1,按一次,他们的状态就翻转一次。

9.2 硬件设计

本实验用到的硬件资源和第七章实验的一模一样,不再多做介绍了。

9.3 软件设计

我们直接打开我们的光盘的实验 3 外部中断实验工程,可以看到相比上一个工程,我们的

HARDWARE 目录下面增加了 exti.c 文件,并且包含了头文件 exti.h。extic.c 文件代码如下:

//外部中断初始化

void EXTI_Init(void)

{

GPIO_InitTypeDef GPIO_Initure;

__HAL_RCC_GPIOA_CLK_ENABLE();

//开启 GPIOA 时钟

__HAL_RCC_GPIOC_CLK_ENABLE(); //开启 GPIOC 时钟

__HAL_RCC_GPIOH_CLK_ENABLE();

//开启 GPIOH 时钟

GPIO_Initure.Pin=GPIO_PIN_0; //PA0

GPIO_Initure.Mode=GPIO_MODE_IT_RISING; //上升沿触发

GPIO_Initure.Pull=GPIO_PULLDOWN;

//下拉

HAL_GPIO_Init(GPIOA,&GPIO_Initure);

GPIO_Initure.Pin=GPIO_PIN_13; //PC13

GPIO_Initure.Mode=GPIO_MODE_IT_FALLING; //下降沿触发

GPIO_Initure.Pull=GPIO_PULLUP;

//上拉

HAL_GPIO_Init(GPIOC,&GPIO_Initure);

GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3; //PH2,3 下降沿触发,上拉

HAL_GPIO_Init(GPIOH,&GPIO_Initure);

//中断线 0

HAL_NVIC_SetPriority(EXTI0_IRQn,2,0); //抢占优先级为 2,子优先级为 0

HAL_NVIC_EnableIRQ(EXTI0_IRQn);

//使能中断线 0

//中断线 2

HAL_NVIC_SetPriority(EXTI2_IRQn,2,1); //抢占优先级为 2,子优先级为 1

HAL_NVIC_EnableIRQ(EXTI2_IRQn);

//使能中断线 2

//中断线 3

HAL_NVIC_SetPriority(EXTI3_IRQn,2,2); //抢占优先级为 2,子优先级为 2

HAL_NVIC_EnableIRQ(EXTI3_IRQn);

//使能中断线 2

//中断线 13

HAL_NVIC_SetPriority(EXTI15_10_IRQn,2,3); //抢占优先级为 3,子优先级为 3

HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); //使能中断线 13

}

//中断服务函数

void EXTI0_IRQHandler(void)

{

HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); //调用中断处理公用函数

}

void EXTI2_IRQHandler(void)

{

HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); //调用中断处理公用函数

}

void EXTI3_IRQHandler(void)

{

HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3); //调用中断处理公用函数

}

void EXTI15_10_IRQHandler(void)

{

HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); //调用中断处理公用函数

}

//中断服务程序中需要做的事情

//在 HAL 库中所有的外部中断服务函数都会调用此函数

//GPIO_Pin:中断引脚号

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

static u8 led0sta=1,led1sta=1;

delay_ms(50); //消抖

switch(GPIO_Pin)

{

case GPIO_PIN_0:

if(WK_UP==1)

//控制 LED0,LED1 互斥点亮

{

led1sta=!led1sta;

led0sta=!led1sta;

LED1(led1sta);

LED0(led0sta);

}

break;

case GPIO_PIN_2:

if(KEY1==0) //控制 LED1 翻转

{

led1sta=!led1sta;

LED1(led1sta);

};

break;

case GPIO_PIN_3:

if(KEY0==0)

//同时控制 LED0,LED1 翻转

{

led1sta=!led1sta;

led0sta=!led0sta;

LED1(led1sta);

LED0(led0sta);

}

break;

case GPIO_PIN_13:

if(KEY2==0)

//控制 LED0 翻转

{

led0sta=!led0sta;

LED0(led0sta);

}

break;

}

}

exti.c 文件总共包含 6 个函数。外部中断初始化函数 void EXTIX_Init 用来配置 IO 口外部中

断相关步骤并使能中断,另一个函数 HAL_GPIO_EXTI_Callback 是外部中断共用回调函数,用

来处理所有外部中断真正的控制逻辑。其他 4 个都是中断服务函数。

void EXTI0_IRQHandler(void)是外部中断 0 的服务函数,负责 KEY_UP 按键的中断检测;

void EXTI2_IRQHandler(void)是外部中断 2 的服务函数,负责 KEY2 按键的中断检测;

void EXTI3_IRQHandler(void)是外部中断 3 的服务函数,负责 KEY1 按键的中断检测;

void EXTI4_IRQHandler(void)是外部中断 4 的服务函数,负责 KEY0 按键的中断检测;

下面我们分别介绍这几个函数。

首先是外部中断初始化函数 void EXTIX_Init(void),该函数内部主要做了两件事情。先是

调用 IO 口初始化函数 HAL_GPIO_Init 来初始化 IO 口,该函数的配置含义请看 9.1 小节中关于

HAL_GPIO_Init 函数讲解,然后设置中断优先级并使能中断线。

接下来我们看看外部中断服务函数,一共 4 个。所有的中断服务函数内部都只调用了同样

一个函数 HAL_GPIO_EXTI_IRQHandler,该函数是外部中断共用入口函数,函数内部会进行中

断标志位清零, 并且调用中断处理共用回调函数 HAL_GPIO_EXTI_Callback。这在 9.1 小节我

们也有详细的讲解。

最后是外部中断回调函数 HAL_GPIO_EXTI_Callback,该函数用来编写真正的外部中断控

制逻辑。该函数有一个入口参数就是 IO 口序号。所以我们在该函数内部,一般通过判断 IO 口

序号值来确定中断是来自哪个 IO 口,也就是哪个中断线,然后编写相应的控制逻辑。所以在

该函数内部,我们通过 switch 语句判断 IO 口来源,例如是来自 GPIO_PIN_0,那么一定是来自

PA0,因为中断线一次只能连接一个 IO 口,而四个 IO 口中序号为 0 的 IO 口只有 PA0,所以中

断线 0 一定是连接 PA0,也就是外部中断由 PA0 触发。在回调函数内部,我们仅仅只是编写了

简单的测试逻辑,通过不同的中断来源来控制 DS0 和 DS1 的状态。

接下来我们看看主函数,main 函数代码如下:

int main(void)

{

Cache_Enable(); //打开 L1-Cache

HAL_Init();

//初始化 HAL 库

Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhz

delay_init(216);

//延时初始化

uart_init(115200);

//串口初始化

LED_Init(); //初始化 LED

EXTI_Init();

//外部中断初始化

while(1)

{

printf("OKrn");

//打印 OK 提示程序运行

delay_ms(1000); //每隔 1s 打印一次

}

}

该部分代码很简单,先进行各项初始化之后,在 while 死循环中不停的打印字符串到串口。

当有某个外部按键按下之后,会触发中断服务函数做出相应的反应。

9.4 下载验证

在编译成功之后,我们就可以下载代码到阿波罗 STM32 开发板上,实际验证一下我们的

程序是否正确。下载代码后,在串口调试助手里面可以看到如图 9.4.1 所示信息:

图 9.4.1 串口收到的数据

从图 9.4.1 可以看出,程序已经在运行了,此时可以通过按下 KEY0、KEY1、KEY2 和

KEY_UP 来观察 DS0、DS1 是否跟着按键的变化而变化。

9.5 STM32CubeMX 配置外部中断

本小节我们将教会大家用 STM32CubeMX 配置外部中断相关的初始化代码。关于

STM32CubeMX 的配置,从本小节开始,我们对于每个实验只讲解实验相关关键配置部分,如

果大家不知道具体怎么进入相关界面,请仔细看看前面几个章节实验。

对于外部中断的配置,首先在 MCU 引脚配置图界面选择相应的 GPIO 设置其模式为外部

中断模式。这里以 PH3 为例,如下图 9.5.1:

图 9.5.1 PH3 引脚配置

使用同样的方法依次配置 PC13 和 PH2/PH3,然后我们打开依次点击 Configuration->GPIO

进入 GPIO 详细配置界面 Pin Configuration,界面会列出 4 个 IO 口的配置信息。我们选中 PA0,

看看此时 IO 口配置信息详情如下图 9.5.2 所示:

图 9.5.2 GPIO 配置详情界面

从上图界面可以看出,当我们配置 IO 口作为外部中断触发引脚之后,其详细配置界面便

只有三个选项。第一个选项 GPIO mode 用来设置外部中断触发方法,上升沿触发还是下降沿触

发还是双边沿触发。第二个选项 GPIO Pull-up/Pull-down 用来设置是默认上拉还是下拉。这两个

参数根据我们前面讲解的外部中断知识就很好理解了。这里除了设置 PA0 为上升沿触发默认下

拉外,其他 IO 口都设置为下降沿触发默认上拉。

配置好 IO 口信息之后,接下来就需要配置 NVIC 中断优先级设置。依次点击

Configuration->NVIC,进入 NVIC 配置界面。在界面可以看到有四个外部中断线可配置,这是

因为我们前面开启了四个 IO 口的外部中断(对应 4 个外部中断线)。我们按照实验讲解,依次

配置四个中断线的 NVIC 即可,配置完成后如下图 9.5.3 所示:

图 9.5.3 NVIC 配置界面

最后生成工程,为了篇幅考虑,这里我们就不再列出生成的关键代码。在 main.c 中生成的

函数 MX_GPIO_Init 和我们实验工程中 exti.c 文件中的函数 EXTI_Init 内容一致,在

stm32f7xx_it.c 中生成了 4 个中断服务函数,和 exti.c 文件中的中断服务函数内容一致。当然,

回调函数 HAL_GPIO_EXTI_Callback 的内容软件是无法自动生成的,需要我们自己编写。

gd32f303 设计中断优先级_ALIENTEK 阿波罗 STM32F767 开发板资料连载第九章 外部中断实验...相关推荐

  1. cc2530定时器和捕获比较_ALIENTEK 阿波罗 STM32F767 开发板资料连载十四章 输入捕获实验...

    1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 http://weixi ...

  2. stm32f767串口下载软件_ALIENTEK 阿波罗 STM32F767 开发板资料连载十四章 输入捕获实验...

    1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第十四章 输入捕获实验 ...

  3. 判断按键值_ALIENTEK 阿波罗 STM32F767 开发板资料连载第七章 按键输入实验

    1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第七章 按键输入实验 上 ...

  4. stm32f767中文手册_ALIENTEK 阿波罗 STM32F767 开发板资料连载第五章 SYSTEM 文件夹

    1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第五章 SYSTEM 文 ...

  5. fastreport masterdata每页都显示_ALIENTEK 阿波罗 STM32F767 开发板资料连载十六章 OLED 显示实验...

    1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 http://weixi ...

  6. c语言头文件格式图片_阿波罗 STM32F767 开发板资料连载第四十九章 图片显示实验...

    1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第四十九章 图片显示实验 ...

  7. application.properties 不识别_阿波罗 STM32F767 开发板资料连载第五十八章 手写识别实验

    1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第五十八章 手写识别实验 ...

  8. 正点原子阿波罗STM32F429开发板资料发布,采用底板+核心板

    正点原子阿波罗STM32F429开发板资料发布,采用底板+核心板.... https://www.amobbs.com/thread-5654611-1-1.html 正点原子STM32开发板 htt ...

  9. stm32l0的停止模式怎么唤醒_探索者 STM32F407 开发板资料连载第二十二章 待机唤醒实验

    1)实验平台:alientek 阿波罗 STM32F767 开发板 2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第二十二章 待机唤醒实 ...

最新文章

  1. C++中const指针用法汇总
  2. 你的团队能通过电梯测试吗?
  3. 矩阵元算法科学家谢翔: Rosetta如何连接隐私计算与AI?
  4. 详解图像直方图均衡化原理,附MATLAB、C、C++源码
  5. VS2005中,C#中跨线程访问控件问题解决方案
  6. 解决鼠标滚动的时候多次执行函数
  7. Oracle 实验4 更新数据
  8. Zabbix(一)安装zabbix监控服务配置与添加agent主机的三种方式
  9. android+mms发送流程,mms发送流程代码版droid.docx
  10. 如何拷贝工程_如何获得微信小游戏跳一跳源码以及源代码组合包括哪些
  11. 元音字母A的发音规则
  12. 视频直播 linux 推流,linux rtmp服务器搭建推流
  13. 常见两个DNS地址(114.114.114.114,8.8.8.8)到底是个啥?
  14. 搜索引擎优化(SEO) 基础常识
  15. 黄河金岸诗词赋联大赛获奖名单
  16. python dos攻击_Python DOS预防十亿笑声攻击
  17. 利用android monkey 抢支付宝红包
  18. 表单_内置Filed
  19. 关于数学计算机手抄报简单的,关于数学的手抄报简单
  20. 图论应用 floyd(弗洛伊德)算法、dijkstra(迪杰斯特拉)算法

热门文章

  1. http://user.qzone.qq.com/383074470/blog/1270631840
  2. 上海宽泛计算机招聘,2022上海市公务员考试职位表
  3. 为教育工作者精选的8款堪称「神器」的软件,快看过来
  4. 听说 Flutter 最近要多火爆就有多火爆,那就推荐一个不错的系列文章吧
  5. 博士招生从1万到10万再到100万
  6. C盘清理瘦身就这三招,收好下次不必到处找。
  7. [线性代数]遗留问题
  8. 测试游戏cpu和显卡占用软件,什么软件能检测游戏频数和cpu占有率?
  9. Shape of passed values is (230999, 1), indices imply (230999, 3)
  10. 长尾词优化的过程控制和方法