Bootstrap

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

Author:AXYZdong

自动化专业 工科男

有一点思考,有一点想法,有一点理性!

定个小小目标,努力成为习惯!在最美的年华遇见更好的自己!

更多精彩文章前往:👉

- 开发板:

- 开发环境:keil5 MDK

一、EXTI 简介

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

二、EXTI 功能框图

  • 信号线上斜杠并标注 “23” 字样 :表示在控制器内部类似的信号线路有23个。

  • 是挂靠在 总线上的。

三、中断/事件线

  • ,通过编程控制可以实现任意一个 GPIO作为EXTI 的输入源

  • 外部中断配置寄存器 1 配置EXTI0

四、EXTI 初始化结构体

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. 中断/事件线

#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 模式

typedef enum
{
  EXTI_Mode_Interrupt = 0x00,  //产生中断
  EXTI_Mode_Event = 0x04       //产生事件
}EXTIMode_TypeDef;

4.3. 触发类型

typedef enum
{
  EXTI_Trigger_Rising = 0x08,         //上升沿
  EXTI_Trigger_Falling = 0x0C,        //下降沿
  EXTI_Trigger_Rising_Falling = 0x10  //上升沿和下降沿都触发
}EXTITrigger_TypeDef;

4.4. EXTI 控制

,一般都是使能,

五、外部中断控制实验

按键作为外部输入,按下按键触发外部中断,进入中断服务函数。

编程要点

  • 初始化LED的GPIO

  • 配置按键GPIO为输入模式

  • 配置NVIC

  • 按键GPIO连接到EXTI输入

  • 配置EXTI中断/事件线

  • EXTI中断服务函数

EXTI.h

// =============================================
# @Time    : 2021-02-18
# @Author  : AXYZdong
# @InfoQ   :https://www.infoq.cn/profile/95CAD506550AB9/publish/all
# @FileName: main.c
# @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

// =============================================
# @Time    : 2021-02-18
# @Author  : AXYZdong
# @InfoQ   :https://www.infoq.cn/profile/95CAD506550AB9/publish/all
# @FileName: main.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

// =============================================
# @Time    : 2021-02-18
# @Author  : AXYZdong
# @InfoQ   :https://www.infoq.cn/profile/95CAD506550AB9/publish/all
# @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需要开启 外部中断配置寄存器的时钟

  • 宏定义的使用可以便于代码移植

【参考文献】

[1] 《零死角玩转 STM32—基于野火 F407[霸天虎]开发板 》

猜你喜欢:

本次的分享就到这里

好书不厌百回读,熟读自知其中意。将学习成为习惯,用知识改变命运,用博客见证成长,用行动证明努力。

如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!

听说 👉 点赞 👈 的人运气不会太差,每一天都会元气满满呦!^ _ ^

码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了👉 关注 👈我哦!

如果以上内容有任何错误或者不准确的地方,欢迎在下面👇留个言。或者你有更好的想法,欢迎一起交流学习~~~