STM32之外部中断+按键

EXIT简介

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

外部中断配置

使用 GPIO 之前必须开启 GPIO 端口的时钟;用到 EXTI 必须开启 AFIO 时钟。因为配置 EXTI 信号源的时候需要用到 AFIO 的外部中断控制寄存器AFIO_EXTICRx

#define KEY1_INT_GPIO_PORT         GPIOA
#define KEY1_INT_GPIO_CLK          (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO)
#define KEY1_INT_GPIO_PIN          GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE    GPIO_PinSource0
#define KEY1_INT_EXTI_LINE         EXTI_Line0
#define KEY1_INT_EXTI_IRQ          EXTI0_IRQn
#define KEY1_IRQHandler            EXTI0_IRQHandler

#define KEY2_INT_GPIO_PORT         GPIOC
#define KEY2_INT_GPIO_CLK          (RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO)
#define KEY2_INT_GPIO_PIN          GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE    GPIO_PinSource13
#define KEY2_INT_EXTI_LINE         EXTI_Line13
#define KEY2_INT_EXTI_IRQ          EXTI15_10_IRQn
#define KEY2_IRQHandler            EXTI15_10_IRQHandler

void EXTI_Key_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure; 			//声明GPIO配置结构体
	EXTI_InitTypeDef EXTI_InitStructure;			//声明外部中断优先级配置结构体
	NVIC_InitTypeDef NVIC_InitStructure;			//声明中断优先级配置结构体

	/*------------------开启按键GPIO口的时钟----------------------*/
	
	RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
												
	/*---------------配置嵌套向量中断控制器NVIC-------------------*/
	//按键1的中断优先级配置
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);				/* 配置NVIC为优先级组1 */
    NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;		/* 配置中断源:按键1 */
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	/* 配置抢占优先级 */
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;			/* 配置子优先级 */
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				/* 使能中断通道 */
    NVIC_Init(&NVIC_InitStructure);	
    //按键2的中断优先级配置
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);				/* 配置NVIC为优先级组1 */
  	NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ; 	/* 配置中断源:按键2 */  
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	/* 配置抢占优先级 */
 	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;			/* 配置子优先级 */
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				/* 使能中断通道 */
  	NVIC_Init(&NVIC_InitStructure);
	
/*--------------------------KEY1配置-----------------------------*/
	
    GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;					/* 选择按键用到的GPIO */	
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;				/* 配置为浮空输入 */	
    GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);

    GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); /* 选择EXTI的信号源 */
    EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;						/* 选择EXIT事件线 */
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;						/* EXTI为中断模式 */
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;					/* 上升沿中断 */
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;								/* 使能中断 */	
    EXTI_Init(&EXTI_InitStructure);
    
/*--------------------------KEY2配置-----------------------------*/
		
    GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;					/* 选择按键用到的GPIO */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;				/* 配置为浮空输入 */	
    GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);

    GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE); /* 选择EXTI的信号源 */
    EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;						/* 选择EXIT事件线 */
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;						/* EXTI为中断模式 */
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;					/* 下降沿中断 */
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;								/* 使能中断 */	
    EXTI_Init(&EXTI_InitStructure);
}

EXTI结构体

  1. EXTI_Line:EXTI 中断/事件线选择,可选 EXTI0 至 EXTI19。
  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)。
int main(void)
{
	/* LED 端口初始化 */
	LED_GPIO_Config();
	/*
	* 初始化EXTI中断,按下按键会触发中断,
  	*  触发中断会进入stm32f4xx_it.c文件中的函数
	*  KEY1_IRQHandler和KEY2_IRQHandler,处理中断,反转LED灯。
	*/
	EXTI_Key_Config(); 
	/* 等待中断,由于使用中断方式,CPU不用轮询按键 */
	while(1)                            
	{}
}

编写中断服务函数

在stm32f10x_it.c文件中编写

void EXTI0_IRQHandler(void)
{
	if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) 	//确保是否产生了EXTI Line中断
	{
        /*进入中断,编写用户代码*/
		EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     //清除中断标志位
	}  
}

void EXTI15_10_IRQHandler(void)
{
	if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET)  //确保是否产生了EXTI Line中断
	{
		/*进入中断,编写用户代码*/
		EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);    //清除中断标志位
	}  
}

EXTI_GetITStatus 函数用来获取 EXTI 的中断标志位状态,如果 EXTI 线有中断发生函数返回“SET”否则返回“RESET”。

EXTI_GetITStatus 函数通过读取EXTI_PR 寄存器值来判断 EXTI 线状态。

中断/事件线

作为中断/事件输入线时需把 GPIO 配置为浮空输入,由外部电路完全决定引脚的状态。
STM32之外部中断+按键

中断向量表

优先级 名称 说明 地址
13 EXTI0 EXTI线0中断 0x0000_0058
14 EXTI1 EXTI线1中断 0x0000_005C
15 EXTI2 EXTI线2中断 0x0000_0060
16 EXTI3 EXTI线3中断 0x0000_0064
17 EXTI4 EXTI线4中断 0x0000_0068
30 EXTI9_5 EXTI线[9:5]中断 0x0000_009C
47 EXTI15_10 EXTI线[15:10]中断 0x0000_00E0
上一篇:【MPU6050】读取地址错误问题,读取ID0,209(0xd1),255


下一篇:树莓派超声波测距