【STM32】外部中断

1.EXTI简介

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

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

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

2.中断/事件线

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

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

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

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

3.外部中断标准库函数

c 复制代码
typedef struct {
    uint32_t EXTI_Line;                 // 中断/事件线
    EXTIMode_TypeDef EXTI_Mode;         // EXTI模式
    EXTITrigger_TypeDef EXTI_Trigger;   // 触发事件
    FunctionalState EXTI_LineCmd;       // EXTI控制
} EXTI_InitTypeDef;
  1. EXTI_Line:EXTI中断/事件线选择, 可选EXTI0至EXTI22,可参考表 18‑1选择。

  2. EXTI_Mode:EXTI模式选择, 可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。

  3. EXTI_Trigger:EXTI边沿触发事件, 可选上升沿触发(EXTI_Trigger_Rising)、下降沿触发( EXTI_Trigger_Falling)或者上升沿和下降沿都触发( EXTI_Trigger_Rising_Falling)。

  4. EXTI_LineCmd:控制是否使能EXTI线, 可选使能EXTI线(ENABLE)或禁用(DISABLE)。

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

  1. 使能SYSCFG时钟,在APB2总线上。
  2. 初始化GPIO口为输入。
  3. 设置IO口与中断线的映射关系。
  4. 初始化线上中断,设置触发条件等。
  5. 配置中断分组(NVIC),并使能中断。
  6. 编写中断服务函数,清除中断标志位。

4.软件实现

我们的电路板没有按键,所以使用一个GPIO接地模拟触发下拉中断,来控制LED翻转。当然手动飞线接地会有毛刺,下文代码没有考虑这些方面的处理。

c 复制代码
#ifndef __BSP_EXTI_H
#define __BSP_EXTI_H

#ifdef __cplusplus
extern "C"{

#endif

#include "stm32f4xx.h"

#define MY_EXTI_LINE            EXTI_Line3
#define MY_EXIT_IRQ             EXTI3_IRQn
#define MY_EXIT_IRQHandler      EXTI3_IRQHandler

//PG3引脚为外部下拉中断的接口
#define MY_EXTI_PIN             GPIO_Pin_3
#define MY_EXTI_GPIO_Port       GPIOG
#define MY_EXTI_GPIO_CLK        RCC_AHB1Periph_GPIOG
#define MY_EXTI_PIN_SOURCE      EXTI_PortSourceGPIOG
#define MY_EXTI_Port_SOURCE     EXTI_PinSource3


void Init_EXTI(void);
	
#ifdef __cplusplus
}
#endif

#endif
c 复制代码
#include "bsp_exti.h"
#include "bsp_led.h"
#include "stdio.h"

void Init_EXTI(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);//使能外部中断时钟
	RCC_APB2PeriphClockCmd(MY_EXTI_GPIO_CLK,ENABLE);//使能GPIO时钟
	
	//初始化GPIO
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Pin=MY_EXTI_PIN;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;
	//GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
	GPIO_InitStruct.GPIO_Speed=GPIO_Fast_Speed;
	GPIO_Init(MY_EXTI_GPIO_Port,&GPIO_InitStruct);
	
	//设置IO口与中断线的映射关系
	SYSCFG_EXTILineConfig(MY_EXTI_PIN_SOURCE,MY_EXTI_Port_SOURCE);
	
	//初始化线上中断,并设置触发条件
	EXTI_InitTypeDef EXIT_InitStruct;
	EXIT_InitStruct.EXTI_Line=MY_EXTI_LINE;
	EXIT_InitStruct.EXTI_LineCmd=ENABLE;
	EXIT_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
	EXIT_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_Init(&EXIT_InitStruct);
	
	//配置中断控制器并使能中断
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel=MY_EXIT_IRQ;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStruct);
}

void MY_EXIT_IRQHandler(void)
{
	//这里的ITStatus可以不需要判断,因为该中断函数就一个Line3。
	//但是其他的中断线会共用一个中断服务函数,所以就需要判断是哪一个中断线
	if(SET==EXTI_GetITStatus(MY_EXTI_LINE))
	{
		LED_TOGGLE();
		EXTI_ClearITPendingBit(MY_EXTI_LINE);
		printf("MY_EXIT_IRQHandler\r\n");
	}
}
c 复制代码
int main(void)
{
	//设置中断分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	
	Init_USART();
	
	Init_LED();
	
	Init_EXTI();
	
  /* Infinite loop */
  while (1)
  {
  }
}
相关推荐
wuyk5557 分钟前
107.FreeRTOS 链表深度解析:从原理到面试满分答案
c语言·开发语言·数据结构·stm32·单片机·链表·面试
hongmai66688812 分钟前
ESP32-WROVER-IE-N4R8:外接天线+8MB内存,专治信号焦虑
笔记·单片机·嵌入式硬件·microsoft·risc-v
恒锐丰科技林技术员26 分钟前
EG11722:高耐压 150V 降压 DC‑DC 电源芯片,工业宽压电源优选方案
经验分享·嵌入式硬件
安河桥。39 分钟前
MIPI CSI-2物理层接口:C-PHY与D-PHY技术规格说明
嵌入式硬件·视频
雾削木42 分钟前
GPIO基本概念
单片机·嵌入式硬件
LCG元2 小时前
STM32 USB CDC 虚拟串口开发实战:从 CubeMX 配置到 printf 重定向与稳定收发
stm32·单片机·嵌入式硬件
zcmodeltech2 小时前
源网荷储一体化沙盘模型多场景控制系统设计——基于STM32与Modbus RTU的源网荷储、多能互补、冷热电三联供全场景联动方案,服务范围覆盖全国
数据库·人工智能·stm32·单片机·嵌入式硬件
一条破秋裤2 小时前
17_ADC原理与转换模式
笔记·stm32·学习
威嵌神州3 小时前
军工加固计算机七大核心特性解析|国产化、宽温、强加固工程实现
嵌入式硬件·计算机网络·fpga开发
Brilliantwxx3 小时前
【STM32】 深度详解总线架构 哈佛总线结构
stm32·嵌入式硬件·架构