STM32--EXTI外部中断

一、什么是外部中断?

外部中断是指由微处理器或微控制器外部引脚(通常是GPIO引脚)上的外部事件触发的中断。这些外部事件可以是来自外部设备、传感器或其他外部信号源的触发。

二、外部中断详细内容

由AFIO时钟管理的寄存器有AFIO_EVCR(时间控制寄存器)、AFIO_MAPR(备用功能重映射和调试IO配置寄存器)、AFIO_EXTICRX(外部中断配置寄存器),所以在配置EXTI时需要先开启AFIO时钟。

1. EXTI总线分布

通过AFIO_EXTICRx配置GPIO线上的外部中断/事件,必须先使能AFIO时钟。
EXTI线0~EXIT线15总线控制GPIO口映射
STM32--EXTI外部中断_第1张图片
● EXTI线16连接到PVD输出。
● EXTI线17连接到RTC闹钟事件。
● EXTI线18连接到USB唤醒事件。
● EXTI线19连接到以太网唤醒事件(只适用于互联型产品) 。

2. EXTI寄存器

STM32--EXTI外部中断_第2张图片
(1)中断屏蔽寄存器(EXTI_IMR): 屏蔽(置0)或开放(置1)来自线x的中断请求。使能/失能中断。

(2) 挂起寄存器(EXTI_PR) : 没有发生(置0) /发生(置1)触发请求。
当在外部中断线上发生了选择的边沿事件,该位被置’1’。在该位中写入’1’可以清除它,也可以通过改变边沿检测的极性清除。

(3) 事件屏蔽寄存器(EXTI_EMR) : 屏蔽(置0)或开放(置1)来自线x的事件请求。使能/失能事件。

(4)上升沿触发选择寄存器(EXTI_RTSR) : 禁止(置0)或允许(置1)输入线x上的上升沿触发(中断和事件) 。

(5)下降沿触发选择寄存器(EXTI_FTSR) : 禁止(置0)或允许(置1)输入线x上的下降沿触发(中断和事件) 。

(6)软件中断事件寄存器(EXTI_SWIER) : 当该位为’0’时,写’1’将设置EXTI_PR中相应的挂起位。如果在EXTI_IMR和EXTI_EMR中允许产生该中断,则此时将产生一个中断。
注:通过清除EXTI_PR的对应位(写入’1’),可以清除该位为’0’。

3. EXTI框架图分析

STM32--EXTI外部中断_第3张图片
(1) 如果采用外设(输入线)来产生中断,可以选择上升/下降/双边沿触发中断。此时软件中断事件寄存器必须写0。因为软件中断事件寄存器和边沿检测电路通过"或门"连接。如果软件中断寄存器置1,那么会直接产生中断信号,那么外设产生或不产生中断都没有作用。 通过在软件中对软件中断/事件寄存器写 1 ,也可以产生中断/事件请求。
(2) EXTI 可分为两大部分功能,一个是产生中断,另一个是产生事件,这两个功能从硬件上就有所不同。
●产生中断线路目的: 是把输入信号输入到 NVIC,进一步会运行中断服务函数,实现功能,这样是软件级的。
●产生事件线路目的: 就是传输一个脉冲信号给其他外设使用,并且是电路级别的信号传输,属于硬件级的。
●产生中断步骤: 根据输入线外设电路需要的边沿检测设置触发寄存器,并将 “软件中断事件寄存器” 置0(原因如上述),同时在 “中断屏蔽寄存器” 的相应位写 1 使能中断请求。当外部中断线上出现选定信号沿时,便会产生中断请求,“请求挂起寄存器” 的对应的挂起位会置1。在 “请求挂起寄存器” 的对应位写 1 ,将清除该中断请求。
●产生事件的步骤: 根据输入线外设电路需要的边沿检测设置触发寄存器,同时在 “事件屏蔽寄存器” 的相应位写 1 允许事件请求。当事件线上出现选定信号沿时,便会产生事件脉冲。
(3)“脉冲发生器” 去触发事件响应,它主要连到其它外设,中断信号来了就激活脉冲发生器,给它连接的其它外设发射一次脉冲信号。
(4) 两个“屏蔽寄存器”。它们都和我们的信号连到了一个 “与门” 上,这就意味着如果把这个屏蔽寄存器的某些位设为 0,来的中断信号就永远过不去这个与门,达到了一个“屏蔽”的效果。例如不希望某个中断通道起作用,那就把中断屏蔽寄存器的那一位设为 0,这里来的中断信号就永远到不了 NVIC;再例如不需要事件响应的功能,那么就把事件屏蔽器全设为 0,事件响应就无效了。

4. EXTI相关配置

(1)EXTI模式:

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

(2)EXTI触发类型:

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

5.EXTI示例:(以 PA10 为例)

(1)使能时钟(因为GPIO映射外部中断,所以需要开启AFIO时钟)

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	// GPIOA 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);	// AFIO 时钟

(2)配置GPIO引脚

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;		// 以上拉输入模式为例
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

(3)配置GPIO口与外部中断线的映射关系。(PA10挂在EXTI10总线上)

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource10);//外部中断线10与PA10相映射。

(4)配置EXTI

EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line10;		// 选择中断线
EXTI_InitStructure.EXTI_LineCmd = ENABLE;		// 使能中断线
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	// 中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;	// 以上升沿触发为例
EXTI_Init(&EXTI_InitStructure);

(5)配置中断优先组

NVIC_PriorityGroupConfig(NVIC_Priority_Group_2);

(6)配置NVIC

NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;		// PA10 选择EXTI15_10 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			// 使能中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	// 抢占优先级,数值范围要注意符合前面分组的规范
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		// 响应优先级,数值范围要注意符合前面分组的规范
NVIC_Init(&NVIC_InitStructure);

(7)编写中断服务函数

void EXTI15_10_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line10) == SET) {	// 判断 PX10 对应的挂起寄存器是否置位,如果置位说明产生了中断
		EXTI_ClearITPendingBit(EXTI_Line10);	// 清除中断标志位
		// 处理你的中断 ...
	}
}

为什么要在中断服务函数中清除中断标志位?
答:在处理外部中断信号时,中断服务程序应该在最后的清除操作中将中断标志位重新设置为“0”,以保证系统正常运行。如果中断标志位没有被清除,那么即使该中断信号已经被处理完毕,处理器仍然会认为该中断信号还没有被处理,从而一直处于中断状态。

6.附录

(1)软件触发中断的库函数.

void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);

你可能感兴趣的:(stm32,单片机,嵌入式硬件,EXTI,外部中断)