hal库开启中断关中断_「正点原子NANO STM32开发板资料连载」第十章 外部中断实验...
1)实验平台:ALIENTEK NANO STM32F411 V1开发板
2)摘自《正点原子STM32F4 开发指南(HAL 库版》关注官方微信号公众号,获取更多资料:正点原子
第十章 外部中断实验
这一章,我们将向大家介绍如何使用 STM32F4 的外部输入中断。在前面几章的学习中,
我们掌握了 STM32F4 的 IO 口最基本的操作。本章我们将介绍如何将 STM32F4 的 IO 口作为外
部中断输入,在本章中,我们将以中断的方式,实现我们在第八章所实现的功能。本章分为如
下几个部分:
10.1 STM32F4 外部中断简介
10.2 硬件设计
10.3 软件设计
10.4 下载验证
10.1 STM32F4 外部中断简介
STM32F4 的 IO 口在第六章有详细介绍,而中断管理分组管理在前面也有详细的阐述。这
里我们将介绍 STM32F4 外部 IO 口的中断功能,通过中断的功能,达到第八章实验的效果,即:
通过板载的 4 个按键,控制板载的两个 LED 的亮灭以及蜂鸣器的发声。
这里我们首先 STM32F4 IO 口中断的一些基础概念。STM32F4 的每个 IO 都可以作为外部
中断的中断输入口,这点也是 STM32F4 的强大之处。STM32F4 的中断控制器支持 23 个外部中
断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。STM32F4 的
23 个外部中断为:
线 0~15:对应外部 IO 口的输入中断。
线 16:连接到 PVD 输出。
线 17:连接到 RTC 闹钟事件。
线 18:连接到 USB OTG FS 唤醒事件。
线 21:连接到 RTC 入侵和时间戳事件。
线 22:连接到 RTC 唤醒事件。
从上面可以看出,STM32 供 IO 口使用的中断线只有 16 个,但是 STM32 的 IO 口却远远不
止 16 个,那么 STM32 是怎么把 16 个中断线和 IO 口一一对应起来的呢?于是 STM32 就这样
设计,GPIO 的管教 GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线 0~15。这样每个中
断线对应了最多 7 个 IO 口,以线 0 为例:它对应了 GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、
GPIOE.0、GPIOF.0、GPIOG.0。而中断线每次只能连接到 1 个 IO 口上,这样就需要通过配置
来决定对应的中断线配置到哪个 GPIO 上了。下面我们看看 GPIO 跟中断线的映射关系图:
图 10.1.1 GPIO 和中断线的映射关系图
GPIO 和中断线映射关系是在寄存器 SYSCFG_EXTICR1~ SYSCFG_EXTICR4 中配置的。
所以我们要配置外部中断,还需要打开 SYSCFG 时钟。
接下来我们来看看使用 HAL 库配置外部的一般步骤。HAL 中外部相关配置函数和定义在
文件 stm32f4xx_hal_exti.h 和 stm32f4xx_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_RSING(外部中断上
升 沿 触 发 ) , GPIO_MODE_IT_FALLING ( 外 部 中 断 下 降 沿 触 发 ) 或 者
GPIO_MODE_IT_RISING_FALLING(外部中断双边沿触发)的时候,该函数内部会通过判断
Mode 的值来配置模式,并且设置 IO 口和中断线的映射关系。
因为我们这样初始的是 PA0,根据图 10.1.1 可知,调用该函数后中断线 0 会自动连接到 PA0。
如果某个时间,我们又同样的方式初始化了 PB0,那么 PA0 与中断线的链接将被清除,而直接
连接 PB0 到中断线 0。
3)配置中断优先级(NVIC),并使能中断。
我们设置好中断线和 GPIO 映射关系,然后又设置好了中断的触发模式等初始化参数。既
然是外部中断,涉及到中断我们当然还要设置 NVIC 中断优先级。这个在前面已经讲解过,这
里我们就接着上面的范例,设置中断线 0 的中断优先级并使能外部中断 0 的方法为:
HAL_NVIC_SetPriority(EXTI0_IRQn,2,2);
//抢占优先级为 2,子优先级为 2
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
//使能中断线 0
上面这段代码相信大家都不陌生,我们在前面的串口实验的时候讲解过,这里不再讲解。
4)编写中断服务函数。
我们配置完中断优先级之后,接着要做的就是编写中断服务函数。中断服务函数的名字是
在 HAL 库中事先有定义的。这里需要说明一下,STM32F4 的 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 讲
解。
4) 编写中断处理回调函数 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);
}
}
该 函 数 实 现 的 作 用 非 常 简 单 , 就 是 清 除 中 断 标 志 位 , 然 后 调 用 回 调 函 数
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 控制蜂鸣器,按一次
叫,再按一次停;KEY1 控制 DS1,按一次亮,再按一次灭;KEY0 控制 DS0,效果同 KEY1。
10.2 硬件设计
本实验用到的硬件资源和第八章实验的一模一样,不再多做介绍了。
10.3 软件设计
我们直接打开我们的光盘的实验 5 外部中断实验工程,可以看到相比上一个工程,我们的
HARDWARE 目录下面增加了 exti.c 文件,并且包含了头文件 exti.h。exti.c 文件代码如下:
//外部中断初始化
void EXTI_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOA_CLK_ENABLE();
//开启 GPIOA 时钟
__HAL_RCC_GPIOC_CLK_ENABLE();
//开启 GPIOC 时钟
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_8|GPIO_PIN_9;
//PC8、PC9
GPIO_Initure.Mode=GPIO_MODE_IT_FALLING; //下降沿触发
GPIO_Initure.Pull=GPIO_PULLUP;
HAL_GPIO_Init(GPIOC,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_2;
//PD2
HAL_GPIO_Init(GPIOD,&GPIO_Initure);
//中断线 0-PA0
HAL_NVIC_SetPriority(EXTI0_IRQn,2,2);
//抢占优先级为 2,子优先级为 2
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
//使能中断线 0
//中断线 8、9-PC8、9
HAL_NVIC_SetPriority(EXTI9_5_IRQn,2,1); //抢占优先级为 2,子优先级为 1
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
//中断线 2-PD2
HAL_NVIC_SetPriority(EXTI2_IRQn,2,0);
//抢占优先级为 2,子优先级为 0
HAL_NVIC_EnableIRQ(EXTI2_IRQn);
//使能中断线 2
}
//中断服务函数
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); //调用中断处理公用函数
}
void EXTI9_5_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8); //调用中断处理公用函数
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9); //调用中断处理公用函数
}
void EXTI2_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); //调用中断处理公用函数
}
//中断服务程序中需要做的事情
//在 HAL 库中所有的外部中断服务函数都会调用此函数
//GPIO_Pin:中断引脚号
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
delay_ms(10);
//消抖
switch(GPIO_Pin)
{
case GPIO_PIN_0:
if(WK_UP==1)
{
LED0=!LED0;
//控制 LED0,LED1 互斥点亮
LED1=!LED1;
}
break;
case GPIO_PIN_8:
if(KEY0==0)
//控制 LED0 翻转
{
LED0=!LED0;
}
break;
case GPIO_PIN_9:
if(KEY1==0)
{
LED1=!LED1;
//控制 LED1 翻转
}
break;
case GPIO_PIN_2:
if(KEY2==0)
{
BEEP=!BEEP;
//控制 BEEP
}
}
}
exit.c 文件总共包含 5 个函数。外部中断初始化函数 void EXTIX_Init 用来配置 IO 口外部中
断相关步骤并使能中断,另一个和函数 HAL_GPIO_EXTI_Callback 是外部中断共用回调函数,
用来处理所有外部中断真正的控制逻辑。其他 3 个都是中断服务函数。
void EXTI0_IRQHandler(void)是外部中断 0 的服务函数,负责 WK_UP 按键的中断检测;
void EXTI2_IRQHandler(void)是外部中断 2 的服务函数,负责 KEY2 按键的中断检测;
void EXTI9_5_IRQHandler(void)是外部中断 5~9 的服务函数,负责 KEY0 和 KEY1 按键的中断检测;
下面我们分别介绍这几个函数。
首先是外部中断初始化函数 void_EXTI_Init(void),该函数内部主要是做了两件事情。首先
是调用 IO 口初始化函数 HAL_GPIO_Init 来初始化 IO 口,该函数的配置含义请看 10.1 小节中
关于 HAL_GOIO_Init 函数讲解。其次是设置中断优先级并使能中断线。
接下来我们看看外部中断服务函数,一共 3 个。所有的中断服务函数内部都只调用了同样
一个函数 HAL_GPIO_EXTI_IRQHandler,该函数是外部中断共用入口函数,函数内部会进行中
断标志位清零,并且调用中断处理共同回调函数 HAL_GPIO_EXTI_Callback。这在 10.1 小节我
们也有详细的讲解。
最后是外部中断回调函数 HAL_GPIO_EXTI_Callback,该函数用来编写真正的外部中断控
制逻辑。该函数有一个入口参数是 IO 口序号。我们我们在该函数内部,一般通过判断 IO 口序
号来确定中断是来自哪个 IO 口,也就是哪个中断线,然后编写相应的控制逻辑。所以在该函
数内部,我们通过 switch 语句判断 IO 口来源,例如是来自 GPIO_PIN_0,那么一定是来自 PA0,
因为中断线一次只能连接一个 IO 口,而四个 IO 口中序号为 0 的 IO 口只有 PA0,所以中断线 0
一定是连接 PA0,也就是外部中断由 PA0 触发。
接下来我们看看主函数,main 函数代码如下:
int main(void)
{
HAL_Init();
//初始化 HAL 库
Stm32_Clock_Init(96,4,2,4);
//设置时钟,96Mhz
delay_init(96);
//初始化延时函数
uart_init(115200);
//初始化串口 115200
LED_Init();
//初始化 LED
KEY_Init();
//初始化按键
BEEP_Init();
//初始化 BEEP
EXTI_Init();
//初始化外部中断
LED0=0;
//点亮 LED
while(1)
{
printf("OK");
//打印 OK 提示程序运行
delay_ms(1000);
//每隔 1s 打印一次
}
}
该部分代码非常简单,先进行各项初始化之后,在 while 死循环中不停的打印字符串到串
口。当有某个外部按键按下之后,会触发中断服务函数做出相应的反应。
10.4 下载验证
在编译成功之后,我们就可以下载代码到 NANO STM32F4 开发板上,实际验证一下我们
的程序是否正确。下载代码后,在串口调试助手里面可以看到如图 10.4.1 所示信息:
图 10.4.1 串口收到的数据
从图 10.4.1 可以看出,程序已经在运行了,此时可以通过按下 KEY0、KEY1、KEY2 和
KEK_UP 来观察 DS0、DS1 以及蜂鸣器是否跟着按键的变化而变化。
10.5 STM32CubeMX 配置外部中断
本 小 节 我 们 将 会 大 家 用 STM32CubeMX 配 置 外 部 中 断 相 关 的 初 始 化 代 码 。 关 于
STM32CubeMX 的配置,本小节开始,我们对于每个实验只讲解实验相关关键配置部分,如果
大家不知道具体怎么进入相关界面,请仔细看看前面几个章节实验。
对于外部中断的配置,首先在 MCU 引脚配置图界面选择对应的 GPIO 设置其模式为外部
中断模式。这里以 PD2 为例,如下图 10.5.1 所示:
图 10.5.1 PD2 引脚配置
使用同样的方法依次配置 PA0 和 PC8/PC9,然后我们打开依次点击 Configuration->GPIO
进入 GPIO 详细配置 Pin Configuration,界面会列车 4 个 IO 口的配置信息。我们选中 PA0,看
看此时 IO 口配置信息详情如下图 10.5.2 所示:
图 10.5.2 GPIO 配置详情界面
从上图界面可以看出,当我们配置 IO 口作为外部中断触发引脚之后,其详细配置界面便
只有三个选项。第一个选项 GPIO mode 用来设置外部中断触发方法,上升沿触发还是下降沿触
发还是双边沿触发。第二个选项 GPIO Pull-up/Pull-down 用来设置是默认上拉还是下拉。这两个
参数根据我们前面讲解的外部中断知识就很好理解了。这里我们除了设置 PA0 为上升沿触发默
认下拉外,其他 IO 口设置为下降沿触发默认上拉。
配置号 IO 口信息之后,接下来就需要配置 NVIC 中断优先级设置。依次点击 System
Core->NVIC,进入 NVIC 配置界面。在界面可以看到有三个外部中断线可配置,这是因为我们
前面开启了四个 IO 外部中断(对应 3 个外部中断线)。我们按照实验讲解,依次配置三个中
断线的 NVIV 即可,配置完成后如下图 10.5.3 所示:
图 10.5.3 NVIC 配置界面
最后生成工程,为了篇幅考虑,这里我们就不再列车生成的关键代码。在 main.c 中生成的
函 数 MX_GPIO_Init 和 我 们 实 验 工 程 中 exti.c 文 件 中 的 函 数 EXTI_Init 内 容 一 致 , 在
stm32f4xx_it.c 中生产了 4 个中断服务函数,在 exti.c 文件中的中断服务函数内容一致。当然,
回调函数 HAL_GPIO_EXTI_Callback 的内容软件是无法自动生成的,需要我们自己编写。
hal库开启中断关中断_「正点原子NANO STM32开发板资料连载」第十章 外部中断实验...相关推荐
- 判断按键值_「正点原子NANO STM32开发板资料连载」第十六章电容触摸按键实验...
1)实验平台:ALIENTEK NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第十六章电容 ...
- 韦东山 IMX6ULL和正点原子_「正点原子NANO STM32开发板资料连载」第三章 MDK5 软件入门1...
1)实验平台:ALIENTEK NANO STM32F411 V1开发板 2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三章 M ...
- stm32看门狗_「正点原子NANO STM32开发板资料连载」第十一章 独立看门狗实验
1)实验平台:ALIENTEK NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第十一章 独 ...
- dev c++怎么调试_「正点原子NANO STM32开发板资料连载」第十八章 USMART 调试组件...
1)实验平台:ALIENTEK NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第十八章 U ...
- 看门狗寄存器c语言代码_「正点原子NANO STM32F103开发板资料连载」第十一章 看门狗实验...
1)实验平台:[正点原子] NANO STM32F103 开发板 2)摘自<正点原子STM32 F1 开发指南(NANO 板-HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 ...
- stm32 文件系统dma大小_「正点原子NANO STM32F103开发板资料连载」第二十二章 DMA 实验...
1)实验平台:[正点原子] NANO STM32F103 开发板 2)摘自<正点原子STM32 F1 开发指南(NANO 板-HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 ...
- 嵌入式实时操作系统ucos-ii_「正点原子NANO STM32开发板资料连载」第三十六章 UCOSII 实验 1任务调度...
1)实验平台:alientek NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三十六章 ...
- 嵌入式实时操作系统ucos-ii_「正点原子NANO STM32开发板资料连载」第三十八章 UCOSII 实验 3...
1)实验平台:alientek NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三十八章 ...
- stm32 ucosii消息队列 串口_正点原子STM32F407探索者开发板资料连载第六十三章 UCOSII 实验...
1)实验平台:alientek 阿波罗 STM32F767 开发板 2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 http://weix ...
最新文章
- 人脸识别屡遭非议 会成为“潘多拉魔盒”吗
- 前端 在浏览器端存储数据
- Day 2: AngularJS —— 对AngularJS的初步认识
- javascript 声明变量var、let、const详解及示例
- 技术生涯二三事(上)
- map中只有一个值 获取_小学数学,为什么一个三角形中最多只有一个直角或一个钝角...
- Oracle 11G 安装详解
- C++ 创建快捷方式的最简单方法
- Elasticsearch--入门-_put post修改数据---全文检索引擎ElasticSearch工作笔记007
- Scrapy爬取小说简单逻辑
- 冒烟测试正确名称是踩雷测试,雷区测试
- Android手机RTMP播放工具(APK,支持秒开)
- Java new一个对象的过程
- CF1467C Three Bags(思维)
- 【ES】Elasticsearch的特点优点 为什么比MySQL快?
- 日期转换成年月日格式java_如何将日,月,年转换为日期格式?
- 字符串str.format()方法的个人整理
- 2011年第36届大连赛区现场赛Board
- matlab向量化 什么意思,什么是“向量化”?
- 现在打开网页总是先显示“网页无法打开”要刷新几次才行,这是怎么回事?
热门文章
- 关于MySQL 主从复制问题
- Unicode 和 UTF-8 有何区别?
- shell命令之(一) 初探grep
- 2015 Multi-University Training Contest 1 - 10010 Y sequence
- 仿赶集网二手物品页面左侧导航
- CS-APP:Section 5.1,Memory aliasing :看上去逻辑一样,执行结果一样吗?
- 设计模式笔记(1)---开篇(文章索引)
- 写程序是最轻松的事情
- 大四可以正式入职吗_三方协议一签,就不是应届生了吗?高校毕业生注意,别错失身份...
- git reset 怎么还原_git reset --hard 操作后的数据恢复