28.EXTI外部中断原理与配置
EXTI外部中断原理与配置
参考资料
开发板配套资料
《STM32Fx开发指南-HAL库版本》-第x章 外部中断实验
STM32Fxxx官方资料:
《STM32Fxx中文参考手册》- 中断和事件
笔记基于正点原子官方视频
视频连接https://www.bilibili.com/video/BV1Wx411d7wT?p=71&spm_id_from=333.1007.top_right_bar_window_history.content.click
如有侵权,联系删除
一、IO口外部中断原理概述
1.STM32控制器支持的外部中断/事件请求:
2.IO口外部中断
① STM32的每个
IO都可以作为外部中断输入。
② 每个外部中断线
可以独立的配置触发方式(上升沿
,下降沿
或者双边沿
触发),触发/屏蔽,专用的状态位。
③ STM32供IO使用的中断线只有16个,但是STM32F系列的IO口多达上百个,STM32F103ZGT6(112个IO口),那么中断线怎么跟IO口对应呢?
3.GPIO和中断线映射关系
在位置:H:\2技术书籍\STM32F429开发指南中书《STM32F4xx中文参考手册》8.2.4小节及以后几小节有相关寄存器的详细介绍。
其中:
SYSCFG 外部中断配置寄存器 1 的低16位配置的是 EXTI0 至 EXTI3
SYSCFG 外部中断配置寄存器 2 的低16位配置的是 EXTI4 至 EXTI7
SYSCFG 外部中断配置寄存器 3 的低16位配置的是 EXTI8 至 EXTI11
SYSCFG 外部中断配置寄存器 4 的低16位配置的是 EXTI12 至 EXTI15
例如:
在 EXTI0 对应的四个位填入 0000,则配置的是 PA[0] 引脚
在 EXTI2 对应的四个位填入 0000,则配置的是 PA[2] 引脚
在 EXTI6 对应的四个位填入 0011,则配置的是 PD[6] 引脚
在 EXTI12 对应的四个位填入 0110,则配置的是 PG[12] 引脚
在 EXTI15 对应的四个位填入 0101,则配置的是 PF[15] 引脚
4.16个中断线就分配16个中断服务函数?
IO口外部中断在中断向量表中只分配了7个中断向量,也就是只能使用7个中断服务函数。
从表中可以看出,外部中断线5~9分配一个中断向量,共用一个服务函数外部中断线10~15分配一个中断向量,共用一个中断服务函数。
5.中断服务函数列表:
EXTI0_IRQHandler EXTI1_IRQHandlerEXTI2_IRQHandler EXTI3_IRQHandler EXTI4_IRQHandler EXTI9_5_IRQHandler EXTI15_10_IRQHandler
二、IO口外部中断HAL库配置方法
1.外部中断操作使用到的函数分布文件
- stm32fxxx_hal_gpio.c
位置:工程模板 - HALLIB - stm32fxxx_hal_gpio.c - stm32fxxx_hal_gpio.h
位置:工程模板 - HALLIB - stm32fxxx_hal_gpio.c - stm32fxxx_hal_gpio.h
2.外部中断配置
- 外部中断的中断线
映射配置
和触发方式
都是在GPIO初始化函数中完成:
GPIO_InitTypeDef GPIO_Initure;GPIO_Initure.Pin=GPIO_PIN_0; //PA0GPIO_Initure.Mode=GPIO_MODE_IT_RISING; //上升沿触发GPIO_Initure.Pull=GPIO_PULLDOWN;HAL_GPIO_Init(GPIOA,&GPIO_Initure);
在上面代码配置GPIO_Initure.Mode时,里面模式的子代码里就有关于触发方式的代码。
在位置:工程模板 - HARDWARE - exit.c 文件中有关于触发方式的代码,如下图:
- 和串口中断一样,HAL库同样提供了外部中断通用处理函数HAL_GPIO_EXTI_IRQHandler,我们在外部中断服务函数中会调用该函数处理中断。
//中断服务函数void EXTI0_IRQHandler(void){HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); //调用中断处理公用函数}void EXTI2_IRQHandler(void){HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); //调用中断处理公用函数}
- HAL_GPIO_EXTI_IRQHandler函数内部通过判断中断来源引脚,最终调用外部中断回调函数HAL_GPIO_EXTI_Callback来处理中断。
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);}}
- 用户最终编写中断处理回调函数来编写中断处理逻辑。
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){switch(GPIO_Pin){case GPIO_PIN_0://控制逻辑break;case GPIO_PIN_2://控制逻辑break;}}
3.外部中断的一般配置步骤
① 使能IO口时钟。
② 初始化IO口,设置触发方式:HAL_GPIO_Init();
③ 设置中断优先级,并使能中断通道。
④ 编写中断服务函数:函数中调用外部中断通用处理函数HAL_GPIO_EXTI_IRQHandler。
⑥ 编写外部中断回调函数:HAL_GPIO_EXTI_Callback;
4.外部中断实验硬件连接
KEY0->PH3 上拉输入,下降沿触发
KEY1->PH2 上拉输入,下降沿触发
KEY2->PC13 上拉输入,下降沿触发
WK_UP->PA0 下拉输入,上升沿触发
三、IO口外部中断实验
实现的功能:
按键KEY0按下: 同时控制LED0和LED1翻转。
按键KEY1按下: LED1状态翻转。
按键KEY2按下: LED0翻转。
按键WK_UP按下:控制LED0和LED1互斥点亮。
这里使用之前的按键输入实验作为模板进行外部中断实验
1.在HARDWARE文件夹下面创建exti.c和exti.h
在HARDWARE文件夹下面创建exti.c和exti.h,并添加到工程中
2.搭建exti.h头文件
1)搭建exti.h框架
3.搭建exti.c头文件
1)搭建exti.c文件框架
2)编写中断服务函数框架
因为使用到了PH3, PH2 , PC13,PA0四个引脚,所以要分别对这四个引脚编写中断服务函数
中断服务列表
EXTI0_IRQHandler EXTI1_IRQHandlerEXTI2_IRQHandler EXTI3_IRQHandler EXTI4_IRQHandler EXTI9_5_IRQHandler EXTI15_10_IRQHandler
可见用到了EXTI0_IRQHandler、EXTI2_IRQHandler、EXTI3_IRQHandler、EXTI15_10_IRQHandler 四个句柄函数,
同样在位置:工程文件 - CORE - starup_stm32f429xx.s中也可以看到配置好的句柄函数
所以在exti.c文件中搭建中断服务函数框架
3)编写外部中断回调函数
在位置:工程文件 - HALLIB - stm32f4xx_hal.c - stm32f4xx_hal_gpio.h 文件中
至此exti.c文件框架搭建完毕
#include “exti.h”
void EXTI_Init(void)
{
}
void EXTI0_IRQHandler(void)
{
}
void EXTI2_IRQHandler(void)
{
}
void EXTI3_IRQHandler(void)
{
}
void EXTI15_10_IRQHandler(void)
{
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
}
4.使能IO口时钟、设置触发方式
按键模式配置
KEY0->PH3 上拉输入,下降沿触发
KEY1->PH2 上拉输入,下降沿触发
KEY2->PC13 上拉输入,下降沿触发
WK_UP->PA0 下拉输入,上升沿触发
因为用到了PA、PC、PH三个IO口,所以要对这三个口进行初始化,然后对IO口模式进行配置,具体使能方式前文按键配置有详细说明。
代码如下
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; //PA0GPIO_Initure.Mode=GPIO_MODE_IT_RISING; //上升沿触发GPIO_Initure.Pull=GPIO_PULLDOWN; //下拉GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速HAL_GPIO_Init(GPIOA,&GPIO_Initure); GPIO_Initure.Pin=GPIO_PIN_13; //PC13GPIO_Initure.Mode=GPIO_MODE_IT_FALLING; //下降沿触发GPIO_Initure.Pull=GPIO_PULLUP; //上拉GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速HAL_GPIO_Init(GPIOC,&GPIO_Initure); GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3; //PH2,3GPIO_Initure.Mode=GPIO_MODE_IT_FALLING; //下降沿触发GPIO_Initure.Pull=GPIO_PULLUP; //上拉GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速HAL_GPIO_Init(GPIOH,&GPIO_Initure);
5.设置中断优先级、使能中断通道
其中共调用了4个中断,所以要配置4条中断线
在位置:工程文件 - HALLIB - stm32f4xx_hal.c - stm32f429xx.h 文件中有中断线函数的头文件名
配置在 HAL_NVIC_SetPriority(EXTI0_IRQn
,2,0); 和 HAL_NVIC_EnableIRQ(EXTI0_IRQn
); 中
//中断线0-PA0HAL_NVIC_SetPriority(EXTI0_IRQn,2,0); //抢占优先级为2,子优先级为0HAL_NVIC_EnableIRQ(EXTI0_IRQn); //使能中断线0//中断线2-PH2HAL_NVIC_SetPriority(EXTI2_IRQn,2,1); //抢占优先级为2,子优先级为1HAL_NVIC_EnableIRQ(EXTI2_IRQn); //使能中断线2//中断线3-PH3HAL_NVIC_SetPriority(EXTI3_IRQn,2,2); //抢占优先级为2,子优先级为2HAL_NVIC_EnableIRQ(EXTI3_IRQn); //使能中断线2//中断线13-PC13HAL_NVIC_SetPriority(EXTI15_10_IRQn,2,3); //抢占优先级为2,子优先级为3HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); //使能中断线13
至此,外部中断初始化函数编写完毕,代码如下
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; //PA0GPIO_Initure.Mode=GPIO_MODE_IT_RISING; //上升沿触发GPIO_Initure.Pull=GPIO_PULLDOWN; //下拉GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速HAL_GPIO_Init(GPIOA,&GPIO_Initure); GPIO_Initure.Pin=GPIO_PIN_13; //PC13GPIO_Initure.Mode=GPIO_MODE_IT_FALLING; //下降沿触发GPIO_Initure.Pull=GPIO_PULLUP; //上拉GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速HAL_GPIO_Init(GPIOC,&GPIO_Initure); GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3; //PH2,3GPIO_Initure.Mode=GPIO_MODE_IT_FALLING; //下降沿触发GPIO_Initure.Pull=GPIO_PULLUP; //上拉GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速HAL_GPIO_Init(GPIOH,&GPIO_Initure);//中断线0-PA0HAL_NVIC_SetPriority(EXTI0_IRQn,2,0); //抢占优先级为2,子优先级为0HAL_NVIC_EnableIRQ(EXTI0_IRQn); //使能中断线0//中断线2-PH2HAL_NVIC_SetPriority(EXTI2_IRQn,2,1); //抢占优先级为2,子优先级为1HAL_NVIC_EnableIRQ(EXTI2_IRQn); //使能中断线2//中断线3-PH3HAL_NVIC_SetPriority(EXTI3_IRQn,2,2); //抢占优先级为2,子优先级为2HAL_NVIC_EnableIRQ(EXTI3_IRQn); //使能中断线2//中断线13-PC13HAL_NVIC_SetPriority(EXTI15_10_IRQn,2,3); //抢占优先级为2,子优先级为3HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); //使能中断线13
}
6.编写中断服务器函数
上文说到,中断服务函数格式如下:
在位置:工程文件 - HALLIB - stm32f4xx_hal.c - stm32f4xx_hal_gpio.h 文件中也有其定义句柄函数名
把该句柄函数放在中断服务器函数中,代码如下
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); //调用中断处理公用函数
}
7.编写外部中断回调函数
因为在HAL库中,有关于位带操作的定义,所以可以直接使用LED0、LED1、KEY0、KEY1、KEY2、WK_UP变量名来编写函数
编写好按键控制逻辑,代码如下
#include "delay.h"
#include "led.h"
#include "key.h"//中断服务程序中需要做的事情
//在HAL库中所有的外部中断服务函数都会调用此函数
//GPIO_Pin:中断引脚号
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{delay_ms(100); //消抖switch(GPIO_Pin){case GPIO_PIN_0:if(WK_UP==1) {LED1=!LED1;//控制LED0,LED1互斥点亮LED0=!LED1;}break;case GPIO_PIN_2:if(KEY1==0) //LED1翻转{LED1=!LED1; }break;case GPIO_PIN_3:if(KEY0==0) //同时控制LED0,LED1翻转 {LED0=!LED0;LED1=!LED1;}break;case GPIO_PIN_13:if(KEY2==0) {LED0=!LED0;//控制LED0翻转}break;}
}
至此,exti.c文件编写完毕,代码如下:
#include "exti.h"
#include "delay.h"
#include "led.h"
#include "key.h"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; //PA0GPIO_Initure.Mode=GPIO_MODE_IT_RISING; //上升沿触发GPIO_Initure.Pull=GPIO_PULLDOWN; //下拉GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速HAL_GPIO_Init(GPIOA,&GPIO_Initure); GPIO_Initure.Pin=GPIO_PIN_13; //PC13GPIO_Initure.Mode=GPIO_MODE_IT_FALLING; //下降沿触发GPIO_Initure.Pull=GPIO_PULLUP; //上拉GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速HAL_GPIO_Init(GPIOC,&GPIO_Initure); GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3; //PH2,3GPIO_Initure.Mode=GPIO_MODE_IT_FALLING; //下降沿触发GPIO_Initure.Pull=GPIO_PULLUP; //上拉GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速HAL_GPIO_Init(GPIOH,&GPIO_Initure);//中断线0-PA0HAL_NVIC_SetPriority(EXTI0_IRQn,2,0); //抢占优先级为2,子优先级为0HAL_NVIC_EnableIRQ(EXTI0_IRQn); //使能中断线0//中断线2-PH2HAL_NVIC_SetPriority(EXTI2_IRQn,2,1); //抢占优先级为2,子优先级为1HAL_NVIC_EnableIRQ(EXTI2_IRQn); //使能中断线2//中断线3-PH3HAL_NVIC_SetPriority(EXTI3_IRQn,2,2); //抢占优先级为2,子优先级为2HAL_NVIC_EnableIRQ(EXTI3_IRQn); //使能中断线2//中断线13-PC13HAL_NVIC_SetPriority(EXTI15_10_IRQn,2,3); //抢占优先级为2,子优先级为3HAL_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)
{delay_ms(100); //消抖switch(GPIO_Pin){case GPIO_PIN_0:if(WK_UP==1) {LED1=!LED1;//控制LED0,LED1互斥点亮LED0=!LED1;}break;case GPIO_PIN_2:if(KEY1==0) //LED1翻转{LED1=!LED1; }break;case GPIO_PIN_3:if(KEY0==0) //同时控制LED0,LED1翻转 {LED0=!LED0;LED1=!LED1;}break;case GPIO_PIN_13:if(KEY2==0) {LED0=!LED0;//控制LED0翻转}break;}
}
8.编写main.c函数
- 引入#include “exti.h” 头文件
- 把初始化按键函数 KEY_Init(); 更改为EXTI_Init();
至此,main.c函数编写完毕,代码如下
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "exti.h"int main(void)
{HAL_Init(); //初始化HAL库 Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhzdelay_init(180); //初始化延时函数uart_init(115200); //初始化USARTLED_Init(); //初始化LED EXTI_Init(); //外部中断初始化while(1){printf("OK\r\n"); //打印OK提示程序运行delay_ms(1000); //每隔1s打印一次 }
}
9.下载到开发板
现象这里不再赘述
至此,IO口外部中断实验结束
28.EXTI外部中断原理与配置相关推荐
- 02、【江科大自化协stm32F103c8t6】笔记之【入门32单片机及EXTI外部中断初始化参数配置】
----------接着上一篇笔记写 四.返回值函数 五.EXTI外部中断 1.配置RCC 2.配置GPIO 3.配置AFIO 4.配置EXTI 5.配置NVIC 中断函数 四.返回值函数 uint8 ...
- STM32学习笔记(三)丨中断系统丨EXTI外部中断(对射式红外传感器计次、旋转编码器计次)
本篇文章包含的内容 一.中断系统 1.1 中断的定义 1.2 中断优先级 1.3 中断的嵌套 1.4 STM32中的中断系统 1.4.1 STM32的中断资源 1.4.2 嵌套中断向量控制器 NVIC ...
- 【MM32F5270开发板试用】GPIO输入+EXTI外部中断例程demo试用
本篇文章来自极术社区与灵动组织的MM32F5270开发板评测活动,更多开发板试用活动请关注极术社区网站.作者:Zeee 前言: 首先,感谢灵动微电子与极术社区给予宝贵的试用机会.借助本次对Plus-F ...
- ESP32 外部中断原理分析 GPIO外部中断实战
ESP32 外部中断原理分析 & GPIO外部中断实战 阅读建议: 有一定Cortex-m架构.Xtensa® 32-bit LX6 架构知识基础. 软件环境 VSCODE-ESP32-I ...
- STM32 EXTI外部中断/事件
一.EXTI外部中断/事件功能框图 1.中断线路:①-②-③-④-⑤ ①输入线:有19个中断/事件输入线(联网型有20个),通过寄存器将这些输入线设置为任意一个GPIO. ②边沿检测电路:选择上升沿触 ...
- STM32中断—EXTI外部中断
5. 中断 本文来自于<STM32--江科大>的笔记整理. 中断系统 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处 ...
- STM32(五)——EXTI外部中断
文章笔记源于--江科大自化协的视频 一. 中断系统 中断 : 在主程序运行过程中,出现特定的中断触发条件,使得CPU暂停当前正在运行的程序,而去处理中断程序,完成后,又返回原来被暂停的位置继续工作 中 ...
- STM32 EXTI外部中断的使用
简介: 1.中断系统 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行 中断优先级:当有多个 ...
- STM32笔记——EXTI外部中断
目录 一.概述 二.主要外设介绍 2.1 AFIO复用IO口 2.2 EXTI简介 EXTI框图: 2.3 NVIC中断优先级分组 三.EXTI外部中断整体结构 四.实验程序 4.1 对射式红外传感器 ...
最新文章
- python到底怎么学-学 Python 到底能帮你解决什么问题 ?
- 【视频课】Pytorch模型分析进阶(可视化,参数量与计算量,计算速度)
- 【CyberSecurityLearning 31】Linux网络信息查看与配置、日志文件的管理、备份及日志服务器的搭建
- Arrays.copyOf()、Arrays.copyOfRange()与System.arraycopy()用法
- 图像编解码:CRF(质量/码率控制)和QP
- 直播 | EMNLP 2020:用语义分割的思路解决不完整话语重写任务
- BBQ Hard dp + 组合数学 + 建模
- Android官方开发文档Training系列课程中文版:分享简单数据之发送简单数据给其它APP
- 2022年移动应用趋势洞察白皮书
- 盘一盘 synchronized (一)—— 从打印Java对象头说起
- 转!面向对象设计原则
- CSDN《老友记》简记
- PPC丢失后,手机信息如何保护?(C#)
- Unity Animator动画状态机 深入理解(一)
- ITK-SNAP自动分割应用示例:如何进行乳腺腺体脂肪体积测量
- APP推广技巧:APP营销推广的八种渠道你一定要了解!
- adblock 屏蔽网站广告 免费
- Python 用 os.listdir() 获取文件列表和筛选特定格式文件
- 手机信号上的G、E、O、3G、H、H+是什么意思?
- 电大计算机毕业论文任务书范文,广播电视大学毕业设计任务书表格.doc