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;
-
EXTI_Line:EXTI中断/事件线选择, 可选EXTI0至EXTI22,可参考表 18‑1选择。
-
EXTI_Mode:EXTI模式选择, 可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。
-
EXTI_Trigger:EXTI边沿触发事件, 可选上升沿触发(EXTI_Trigger_Rising)、下降沿触发( EXTI_Trigger_Falling)或者上升沿和下降沿都触发( EXTI_Trigger_Rising_Falling)。
-
EXTI_LineCmd:控制是否使能EXTI线, 可选使能EXTI线(ENABLE)或禁用(DISABLE)。
外部中断的一般配置步骤:
- 使能SYSCFG时钟,在APB2总线上。
- 初始化GPIO口为输入。
- 设置IO口与中断线的映射关系。
- 初始化线上中断,设置触发条件等。
- 配置中断分组(NVIC),并使能中断。
- 编写中断服务函数,清除中断标志位。
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)
{
}
}