【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)的EXTI0[3: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)
  {
  }
}
相关推荐
基极向上的三极管1 小时前
【AD】3-4 在原理图中放置元件
嵌入式硬件
徐嵌1 小时前
STM32项目---水质水位检测
stm32·单片机·嵌入式硬件
徐嵌1 小时前
STM32项目---畜牧定位器
c语言·stm32·单片机·物联网·iot
lantiandianzi1 小时前
基于单片机的老人生活安全监测系统
单片机·嵌入式硬件·生活
东胜物联2 小时前
探寻5G工业网关市场,5G工业网关品牌解析
人工智能·嵌入式硬件·5g
stm32发烧友2 小时前
基于STM32的智能家居环境监测系统设计
stm32·嵌入式硬件·智能家居
hairenjing11239 小时前
使用 Mac 数据恢复从 iPhoto 图库中恢复照片
windows·stm32·嵌入式硬件·macos·word
模拟IC攻城狮11 小时前
华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目——共8套(每套四十题)
嵌入式硬件·华为·硬件架构·芯片
IT B业生11 小时前
51单片机教程(六)- LED流水灯
单片机·嵌入式硬件·51单片机
一枝小雨11 小时前
51单片机学习心得2(基于STC89C52):串口通信(UART)
单片机·嵌入式硬件·51单片机