开发板:stm32f407VET6
- 开发环境:keil5 MDK
一、EXTI 简介
外部中断/事件控制器(EXTI)管理了控制器的 23个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。
二、EXTI 功能框图
- 信号线上斜杠并标注 “23” 字样 :表示在控制器内部类似的信号线路有23个。
EXTI
是挂靠在APB2
总线上的。
三、中断/事件线
中断/事件线 | 输入源 |
---|---|
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,I) |
EXTI16 | 可编程电压检测器(PVD)输出 |
EXTI17 | RTC 闹钟事件 |
EXTI18 | USB OTG FS 唤醒事件 |
EXTI19 | 以太网唤醒事件 |
EXTI20 | USB OTG HS(在 FS 中配置)唤醒事件 |
EXTI21 | RTC 入侵和时间戳事件 |
EXTI22 | RTC 唤醒事件 |
EXTI0至 EXTI15用于 GPIO
,通过编程控制可以实现任意一个 GPIO作为EXTI 的输入源SYSCFG
外部中断配置寄存器 1 配置EXTI0
▲ EXTI0输入源选择
四、EXTI 初始化结构体
代码语言:javascript复制typedef struct
{
//中断/事件线
uint32_t EXTI_Line; /*!< Specifies the EXTI lines to be enabled or disabled.
This parameter can be any combination value of @ref EXTI_Lines */
//EXTI 模式
EXTIMode_TypeDef EXTI_Mode; /*!< Specifies the mode for the EXTI lines.
This parameter can be a value of @ref EXTIMode_TypeDef */
//触发类型
EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines.
This parameter can be a value of @ref EXTITrigger_TypeDef */
//EXTI 控制
FunctionalState EXTI_LineCmd; /*!< Specifies the new state of the selected EXTI lines.
This parameter can be set either to ENABLE or DISABLE */
}EXTI_InitTypeDef;
4.1. 中断/事件线
代码语言:javascript复制#define EXTI_Line0 ((uint32_t)0x00001) /*!< External interrupt line 0 */
#define EXTI_Line1 ((uint32_t)0x00002) /*!< External interrupt line 1 */
#define EXTI_Line2 ((uint32_t)0x00004) /*!< External interrupt line 2 */
#define EXTI_Line3 ((uint32_t)0x00008) /*!< External interrupt line 3 */
#define EXTI_Line4 ((uint32_t)0x00010) /*!< External interrupt line 4 */
#define EXTI_Line5 ((uint32_t)0x00020) /*!< External interrupt line 5 */
#define EXTI_Line6 ((uint32_t)0x00040) /*!< External interrupt line 6 */
#define EXTI_Line7 ((uint32_t)0x00080) /*!< External interrupt line 7 */
#define EXTI_Line8 ((uint32_t)0x00100) /*!< External interrupt line 8 */
#define EXTI_Line9 ((uint32_t)0x00200) /*!< External interrupt line 9 */
#define EXTI_Line10 ((uint32_t)0x00400) /*!< External interrupt line 10 */
#define EXTI_Line11 ((uint32_t)0x00800) /*!< External interrupt line 11 */
#define EXTI_Line12 ((uint32_t)0x01000) /*!< External interrupt line 12 */
#define EXTI_Line13 ((uint32_t)0x02000) /*!< External interrupt line 13 */
#define EXTI_Line14 ((uint32_t)0x04000) /*!< External interrupt line 14 */
#define EXTI_Line15 ((uint32_t)0x08000) /*!< External interrupt line 15 */
#define EXTI_Line16 ((uint32_t)0x10000) /*!< External interrupt line 16 Connected to the PVD Output */
#define EXTI_Line17 ((uint32_t)0x20000) /*!< External interrupt line 17 Connected to the RTC Alarm event */
#define EXTI_Line18 ((uint32_t)0x40000) /*!< External interrupt line 18 Connected to the USB OTG FS Wakeup from suspend event */
#define EXTI_Line19 ((uint32_t)0x80000) /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */
#define EXTI_Line20 ((uint32_t)0x00100000) /*!< External interrupt line 20 Connected to the USB OTG HS (configured in FS) Wakeup event */
#define EXTI_Line21 ((uint32_t)0x00200000) /*!< External interrupt line 21 Connected to the RTC Tamper and Time Stamp events */
#define EXTI_Line22 ((uint32_t)0x00400000) /*!< External interrupt line 22 Connected to the RTC Wakeup event */
4.2. EXTI 模式
代码语言:javascript复制typedef enum
{
EXTI_Mode_Interrupt = 0x00, //产生中断
EXTI_Mode_Event = 0x04 //产生事件
}EXTIMode_TypeDef;
4.3. 触发类型
代码语言:javascript复制typedef enum
{
EXTI_Trigger_Rising = 0x08, //上升沿
EXTI_Trigger_Falling = 0x0C, //下降沿
EXTI_Trigger_Rising_Falling = 0x10 //上升沿和下降沿都触发
}EXTITrigger_TypeDef;
4.4. EXTI 控制
使能 EXTI
,一般都是使能,ENABLE
五、外部中断控制实验
按键作为外部输入,按下按键触发外部中断,进入中断服务函数。
编程要点
- 初始化LED的GPIO
开启按键GPIO时钟和SYSCFG时钟
- 配置按键GPIO为输入模式
- 配置NVIC
- 按键GPIO连接到EXTI输入
- 配置EXTI中断/事件线
- EXTI中断服务函数
EXTI.h
代码语言:javascript复制// =============================================
# @Time : 2020-10-09
# @Author : AXYZdong
# @CSDN : https://blog.csdn.net/qq_43328313
# @FileName: exti.h
# @Software: keil5 MDK
// =============================================
#ifndef _EXTI_H
#define _EXTI_H
//引脚宏定义
/*******************************************************/
#define KEY1_EXTI_PORTSOURCE EXTI_PortSourceGPIOE
#define KEY1_EXTI_PINSOURCE EXTI_PinSource3
#define KEY1_EXTI_LINE EXTI_Line3
#define KEY1_EXTI_IRQ EXTI3_IRQn
#define KET1_IRQHandler EXTI3_IRQHandler
void EXTI_Config(void);
#endif
EXTI.c
代码语言:javascript复制// =============================================
# @Time : 2020-10-09
# @Author : AXYZdong
# @CSDN : https://blog.csdn.net/qq_43328313
# @FileName: EXTI.c
# @Software: keil5 MDK
// =============================================
#include "stm32f4xx.h"
#include "exti.h"
#include "bsp_key.h"
#include "delay.h"
uint8_t flag = 0x00;
void EXTI_Config(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* 使能 SYSCFG 时钟 ,使用 GPIO 外部中断时必须使能 SYSCFG 时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* 连接 EXTI 中断源 到 key1 引脚 */
SYSCFG_EXTILineConfig(KEY1_EXTI_PORTSOURCE, KEY1_EXTI_PINSOURCE);
EXTI_InitStructure.EXTI_Line = KEY1_EXTI_LINE; //连接中断源
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中断
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = KEY1_EXTI_IRQ; //中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority =1; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
}
void KET1_IRQHandler(void)
{
delay_ms(10);
if(KEY1 == RESET)
{
flag ;
flag &= 0x01;
flag == RESET ? GPIO_SetBits(GPIOA,GPIO_Pin_6) : GPIO_ResetBits(GPIOA,GPIO_Pin_6);
}
while(!KEY1);
EXTI_ClearITPendingBit(KEY1_EXTI_LINE);
}
main.c
代码语言:javascript复制// =============================================
# @Time : 2020-10-09
# @Author : AXYZdong
# @CSDN : https://blog.csdn.net/qq_43328313
# @FileName: main.c
# @Software: keil5 MDK
// =============================================
#include "stm32f4xx.h"
#include "bsp_led.h"
#include "bsp_key.h"
#include "sys.h"
#include "delay.h"
#include "exti.h"
int main()
{
delay_init(168); //初始化延时函数
LED_GPIO_Config(); //初始化LED端口
KEY_Init(); //初始化与按键连接的硬件接口
EXTI_Config(); //初始化外部中断
while(1)
{
}
}
实验现象
按下 KEY1 并弹开,LED点亮。再按下 KEY1 并弹开,LED熄灭。
六、总结
- 注意 .h 文件中 EXTI 中断/事件线的配置
- 与 f103 不同,f407需要开启
SYSCFG
外部中断配置寄存器的时钟 - 宏定义的使用可以便于代码移植
【参考文献】
[1] 《零死角玩转 STM32—基于野火 F407[霸天虎]开发板 》