【嵌入式】STM32-外部中断/事件控制器(EXTI)详解.《实例:外部中断实现LED亮灭翻转》

一、EXTI简介

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

二、EXTI功能框图

在这里插入图片描述

1、EXTI 可分为两大部分功能,一个是产生中断,另一个是产生事件。
2、EXTI 控制器有 19 个中断/事件输入线这些输入线可以通过寄存器设置为任意一个 GPIO、或者外设的一些其他事件。
3、对于边沿检测电路,通过控制上升沿触发选择寄存器(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR)的对应位设置触发方式。
4、中断触发可以分别来自来自外输入线、软件中断事件寄存器(EXTI_SWIER)。从结构框图,他们之间通过一个或门连接。
5、挂起寄存器(EXTI_PR)如果有中断发生,对应寄存器为1
6、中断屏蔽寄存器(EXTI_IMR)可以屏蔽中断。
7、最后将 EXTI_PR 寄存器内容输出到 NVIC 内,从而实现系统中断事件控制.
8、产生事件,同理。脉冲信号,是产生事件的线路最终的产物,这个脉冲信号可以给其他外设电路使用,比如定时器 TIM、模拟数字转换器 ADC 等等,这样的脉冲信号一般用来触发 TIM 或者 ADC 开始转换。

三、编程

把握住以下几点:

1、EXTI 有 20 个中断/事件线,每个 GPIO 都可以被设置为输入线。
2、EXTI0EXTI15 用于 GPIO,通过编程控制可以实现任意一个 GPIO 作为 EXTI 的输入源。
3、EXTI在配置的的时候,需要开启复用时钟(RCC_AFIO
4、EXTI 中断/事件线
在这里插入图片描述
在这里插入图片描述

上面的图,代表EXTIn的是输入,可以是PXn(X = A,B,C,D,E,F,G)(n=1,2…15)

1. 编程要点
1) 初始化用来产生中断的 GPIO;
2) 初始化 EXTI;
3) 配置 NVIC;
4) 编写中断服务函数;

配置GPIO,和按键类似,浮空输入模式即可,

四、实例:

“实现按键控制LED亮灭翻转”

1) 初始化用来产生中断的 GPIO;

void KEY_GPIO_Config(void)
{
    
    
	GPIO_InitTypeDef GPIO_InitStruct;
	
	RCC_APB2PeriphClockCmd(GPIO_KEY1_CLK|
						   GPIO_KEY2_CLK|
	                       GPIO_KEY3_CLK|
	                       GPIO_KEY4_CLK|
						   RCC_APB2Periph_AFIO,ENABLE);
												//RCC_APB2Periph_AFIO
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	
	GPIO_InitStruct.GPIO_Pin = GPIO_KEY1_PIN;
	GPIO_Init(GPIO_KEY1_PORT,&GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Pin = GPIO_KEY2_PIN;
	GPIO_Init(GPIO_KEY2_PORT,&GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Pin = GPIO_KEY3_PIN;
	GPIO_Init(GPIO_KEY3_PORT,&GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Pin = GPIO_KEY4_PIN;
	GPIO_Init(GPIO_KEY4_PORT,&GPIO_InitStruct);
	
}

2) 初始化 EXTI;

void EXTI_Config(void)
{
    
    
	EXTI_InitTypeDef EXTI_InitStruct;
	
	NVIC_Config();
	
	//为什么我额外使能一下RCC_AFIO 程序会出错,  PS现在好像不错了
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

	//配置EXTI结构体
	GPIO_EXTILineConfig( KEY1_INT_EXTI_PortSourse, KEY1_INT_EXTI_PinSourse);//选择EXTI的信号源
	
	EXTI_InitStruct.EXTI_Line = KEY1_INT_EXTI_Line;
	EXTI_InitStruct.EXTI_LineCmd = ENABLE;
	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;		//KEY1
	EXTI_Init(&EXTI_InitStruct);
	
	GPIO_EXTILineConfig(KEY2_INT_EXTI_PortSourse, KEY2_INT_EXTI_PinSourse);//选择EXTI的信号源
	EXTI_InitStruct.EXTI_Line = KEY2_INT_EXTI_Line; 		//KEY2
	EXTI_Init(&EXTI_InitStruct);
	
	GPIO_EXTILineConfig(KEY3_INT_EXTI_PortSourse, KEY3_INT_EXTI_PinSourse);//选择EXTI的信号源
	EXTI_InitStruct.EXTI_Line = KEY3_INT_EXTI_Line; 		//KEY3
	EXTI_Init(&EXTI_InitStruct);
	
	GPIO_EXTILineConfig(KEY4_EXTI_PortSourse, KEY4_EXTI_PinSourse);//选择EXTI的信号源
	EXTI_InitStruct.EXTI_Line = KEY4_EXTI_Line; 			//KEY4
	EXTI_Init(&EXTI_InitStruct);
}

3) 配置 NVIC;

void NVIC_Config(void)
{
    
    
	NVIC_InitTypeDef NVIC_InitStruct;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//配置NVIC为优先级组1
	
	NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;				//KEY1
	NVIC_Init(&NVIC_InitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;  			//KEY2
	NVIC_Init(&NVIC_InitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn;  				//KEY3
	NVIC_Init(&NVIC_InitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel = EXTI2_IRQn;  				//KEY4
	NVIC_Init(&NVIC_InitStruct);
}

4) 编写中断服务函数;

void EXTI0_IRQHandler(void)						//KEY1
{
    
    
	if(EXTI_GetITStatus(KEY1_INT_EXTI_Line))
	{
    
    
		LED_1_TOGGLE;
		EXTI_ClearITPendingBit(KEY1_INT_EXTI_Line);
	}

	
}
void EXTI9_5_IRQHandler(void)					//KEY2
{
    
    

	if(EXTI_GetITStatus(KEY2_INT_EXTI_Line))
	{
    
    
		LED_2_TOGGLE;
		EXTI_ClearITPendingBit(KEY2_INT_EXTI_Line);
	}

	
}
void EXTI1_IRQHandler(void)						//KEY3
{
    
    
	
	if(EXTI_GetITStatus(KEY3_INT_EXTI_Line))
	{
    
    
		LED_3_TOGGLE;
		EXTI_ClearITPendingBit(KEY3_INT_EXTI_Line);
	}
	
	
}
void EXTI2_IRQHandler(void)						//KEY4
{
    
    
	
	if(EXTI_GetITStatus(KEY4_EXTI_Line))
	{
    
    
		LED_4_TOGGLE;
		EXTI_ClearITPendingBit(KEY4_EXTI_Line);
	}
	
}

有问题可以留言,欢迎交流探讨!

猜你喜欢

转载自blog.csdn.net/qq_45689790/article/details/113847739