【STM32】EXTI---外部中断/事件控制器

2020-10-29 09:45:48 浏览数 (1)

开发板: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[霸天虎]开发板 》

0 人点赞