STM32 EXTI(外部中断)
一、EXTI 简介
EXTI(External interrupt/event controller)—外部中断/事件控制器,管理了控制器的 20个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。
二、EXTI框图
在图中可以看到很多在信号线上打一个斜杠并标注“20”字样,这表示在控制器内部的信号线有 20 路,我们只要明白其中一路的原理即可。
- 输入线:EXTI 控制器有 20 个中断/事件输入线,这些输入线可以通过寄存器设置为任意一个 GPIO,也可以是一些外设的事件,输入线一般是存在电平变化的信号。
- 边沿检测电路:它会根据上升沿触发选择寄存(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR)对应位的设置来控制信号触发。边沿检测电路以输入线作为信号输入端,如果检测到有边沿跳变就输出有效信号 1 ,否则输出无效信号0。而 EXTI_RTSR 和 EXTI_FTSR 两个寄存器可以控制器需要检测哪些类型的电平跳变过程,可以是只有上升沿触发、只有下降沿触发或者上升沿和下降沿都触发。
- NVIC中断控制器:NVIC中断控制器接收到EXTI_PR 寄存器发送的内容,实现中断的发生。
- 脉冲发生器:脉冲发生器发送信号后会产生事件线路,脉冲信号可以给其他外设电路使用,比如定时器 TIM、模拟数字转换器 ADC等等,这样的脉冲信号一般用来触发 TIM 或者 ADC开始转换。
现在可以知道EXTI 可分为两大部分功能,一个是产生中断,另一个是产生事件。产生中断线路目的是把输入信号输入到 NVIC,进一步会运行中断服务函数,实现功能,这样是软件级的。而产生事件线路目的就是传输一个脉冲信号给其他外设使用,并且是电路级别的信号传输,属于硬件级的。
三、中断/事件线
EXTI有 20个中断/事件线,每个 GPIO都可以被设置为输入线,每个输入线的来源如图所示:
从图中可以看出STM32的外部中断只有16个,又是怎么使每个GPIO都可以实现中断了,通过编程控制可以实现任意一个 GPIO作为 EXTI的输入源。
从上图可知EXTI0 可以通过 AFIO 的外部中断配置寄存器 1(AFIO_EXTICR1)的EXTI0[3:0]位选择配置为 PA0、PB0、PC0、PD0、PE0、PF0、PG0,其他 EXTI线(EXTI中断/事件线)使用配置都是类似的。
四、EXTI 寄存器
中断屏蔽寄存器(EXTI_IMR)
事件屏蔽寄存器(EXTI_EMR)
上升沿触发选择寄存器(EXTI_RTSR)
注意: 外部唤醒线是边沿触发的,这些线上不能出现毛刺信号。在写EXTI_RTSR寄存器时,在外部中断线上的上升沿信号不能被识别,挂起位也不会被置位。在同一中断线上,可以同时设置上升沿和下降沿触发。即任一边沿都可触发中断下降沿触发选择寄存器(EXTI_FTSR)
注意: 外部唤醒线是边沿触发的,这些线上不能出现毛刺信号。在写EXTI_FTSR寄存器时,在外部中断线上的下降沿信号不能被识别,挂起位不会被置位。在同一中断线上,可以同时设置上升沿和下降沿触发。即任一边沿都可触发中断。软件中断事件寄存器(EXTI_SWIER)
挂起寄存器(EXTI_PR)
外部中断/事件寄存器映像
五、EXTI 程序分析
- EXTI 初始化程序的结构体
typedef struct
{
uint32_t EXTI_Line; // 中断/事件线
EXTIMode_TypeDef EXTI_Mode; // EXTI 模式
EXTITrigger_TypeDef EXTI_Trigger; // 触发类型
FunctionalState EXTI_LineCmd; // EXTI 使能
}EXTI_InitTypeDef;
- 初始化GPIO
//将GPIOA_0设置为下拉输入
void KEY_Init(void) //IO初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能PORTB,PORTE时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能AFIO复用功能时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 0 pin
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 设置成下拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA_0
}
- 初始化EXTI
//GPIOA_0 中断线以及中断初始化配置 下降沿触发
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); // 选择GPIOA_0作为中断EXTI0的线路
EXTI_InitStructure.EXTI_Line=EXTI_Line0; //中断/事件线
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 中断触发
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // 下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
}
- 配置 GPIO 中断
//初始化中断
void NVICX_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键WK_UP所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
}
- 中断程序
这里的功能是当按键触发后切换led的状态
//外部中断2服务程序
void EXTI0_IRQHandler(void)
{
Delay(100);//消抖
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1) //检测按键
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==1) //检测led灯的状态,进行切换
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
}else{
GPIO_SetBits(GPIOB,GPIO_Pin_12);
}
}
EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位
}
注意:配置中断函数时,先确保提供的头文件中有相应的中断函数,否则会报错
六、程序源码
main.c 文件
#include "stm32f10x.h"
#include "stm32f10x_exti.h"
#include "misc.h"
/*************** 配置LED用到的I/O口 *******************/
void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE); // 使能PC端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //选择对应的引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PC端口
GPIO_SetBits(GPIOB, GPIO_Pin_12 ); // 关闭LED
}
void Delay(__IO u32 nCount)
{
for(; nCount != 0; nCount--);
}
//将GPIOA_0设置为下拉输入
void KEY_Init(void) //IO初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能PORTB,PORTE时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能AFIO复用功能时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 0 pin
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 设置成下拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA_0
}
/* 配置PA0为外部中断 */
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); // 选择GPIOA_0作为中断EXTI0的线路
EXTI_InitStructure.EXTI_Line=EXTI_Line0; //中断/事件线
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 中断触发
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // 下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
}
//初始化中断
void NVICX_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键WK_UP所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
}
//外部中断2服务程序
void EXTI0_IRQHandler(void)
{
Delay(100);//消抖
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1) //WK_UP按键
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==1)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
}else{
GPIO_SetBits(GPIOB,GPIO_Pin_12);
}
}
EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位
}
int main(void)
{
SystemInit();
LED_GPIO_Config(); //LED 端口初始化
KEY_Init();
EXTIX_Init();
NVICX_Init();
while (1)
{
}
}
七、编译运行
编译完成后下载程序并观察运行现象,当GPIOA_0引脚接地一次,LED灯的状态便切换一次
参考文献
STM32系统学习——EXTI(外部中断):https://blog.csdn.net/zxh1592000/article/details/80280715
STM32之EXTI——外部中断:https://www.cnblogs.com/alvis-jing/p/3678285.html
STM32 EXTI(外部中断)的更多相关文章
- STM32之EXTI——外部中断
互联网的广大网友,大家早上中午晚上好.EXTI...故名思义..EX表外,出..I表示Intrrupt..所以合起来就是外部中断...说到这..我觉得我最近的六级水平(背单词)又进了一步,稍微自夸了下 ...
- STM32之外部中断控制
一.STM32外部中断 1.STM32外部中断结构图 如上图所示:主要包括四个环节,GPIO.AFIO.EXTI.NVIC.以STM32F103VE(100脚)为例说明硬件模块的数量: GPIO: ...
- STM32的外部中断配置及使用
STM32的外部中断配置及使用 配置1:GPIO: 配置外部中断为输入模式: 配置2:EXTI: 配置外部中断线和触发模式: 配置3:NVIC: 配置外部中断源和中断优先级: 需要注意的是:RCC_A ...
- 第17章 EXTI—外部中断/事件控制器
第17章 EXTI—外部中断/事件控制器 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.co ...
- 第17章 EXTI—外部中断/事件控制器—零死角玩转STM32-F429系列
第17章 EXTI—外部中断/事件控制器 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.co ...
- STM32 GPIO外部中断总结
一.STM32中断分组: STM32 的每一个GPIO都能配置成一个外部中断触发源,这点也是 STM32 的强大之处.STM32 通过根据引脚的序号不同将众多中断触发源分成不同的组,比如:PA0,PB ...
- EXTI—外部中断/事件控制器
外部中断/事件控制器(EXTI)管理了控制器的 23 个中断/事件线.每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测. EXTI 可以实现对每个中断/事件线进行单独 ...
- 浅谈stm32的外部中断
简述 本文简单介绍stm32外部中断的一般操作步骤,后续会补充外部中断的相关内容 stm32的中断控制器支持19个外部中断/事件请求: line0~line15:这16条line分别对应不同GPIO口 ...
- STM32之外部中断
图1.0 图1.1 中断控制器支持23条中断线,其中16条是IO管脚中断线,分别是EXTI0~EXTI15: 图 1.2 另外七根中断线如下图: 中断线和管脚的对应关系:EXTI0~EXTI15 和 ...
随机推荐
- Spring中基于注解方式管理bean
操作步骤 第一步:导入相关jar包 spring IoC的基本包 Spring支持注解的Jar包 第二步:创建Spring配置文件,ApplicationContext.xml 引入约束和开启注解扫描 ...
- ciscn_2019_s_3 一道收获很多的题(进步大只能说明基础差)
32位与64位 系统调用的区别: 1. 传参方式不同 2. 系统调用号 不同 3. 调用方式 不同 32位: 传参方式:首先将系统调用号 传入 eax,然后将参数 从左到右 依次存入 ebx,ecx, ...
- CF999B Reversing Encryption 题解
Content 给一个长度为 \(n\) 的字符串 \(s\),执行以下操作: 降序遍历 \(n\) 的所有因子(从 \(n\) 到 \(1\)). 对于每一个因子 \(i\) 翻转字符串 \(s_{ ...
- .NET Core基础篇之:白话管道中间件
在.Net Core中,管道往往伴随着请求一起出现.客户端发起Http请求,服务端去响应这个请求,之间的过程都在管道内进行. 举一个生活中比较常见的例子:旅游景区. 我们都知道,有些景区大门离景区很远 ...
- Windows 数据盘自动分区脚本
在CMD命令文本下执行,即可: diskpart //1.进入diskpart模式 list disk //2.查询磁盘 select disk 1 //3.选择磁盘 create partition ...
- libevent源码学习(11):超时管理之min_heap
目录min_heap的定义向min_heap中添加eventmin_heap中event的激活以下源码均基于libevent-2.0.21-stable. 在前文中,分析了小顶堆min_h ...
- JAVAWEB进行PC支付宝支付、查询订单支付状态
官方文档:https://opendocs.alipay.com/open/270/105899 本地开发环境支付回调调试方法可以参考:https://www.cnblogs.com/pxblog/p ...
- 【LeetCode】978. Longest Turbulent Subarray 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 虫取法 日期 题目地址:https://leetco ...
- Pebbles(hdu2167)
Pebbles Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...
- Codeforces 339B:Xenia and Ringroad(水题)
time limit per test : 2 seconds memory limit per test : 256 megabytes input : standard input output ...