STM32之EXTI外部中断

1.中断简介

中断:在主程序运行中,出现特定的中断触发条件(中断源),使CPU暂停当前程序,转而去执行中断程序,处理完成后又返回原来被暂停的位置继续运行

中断优先级:当有多个中断源同时申请中断时,CPU根据中断源的轻重缓急进行裁决,优先响应更紧急的的中断源

中断嵌套:当一个中断程序正在运行时,有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次返回

中断执行流程图:

执行流程图

2.NVIC中断管理

中断优先级分组

对STM32中断进行分组,组0~4。同时,对每个中断设置一个抢占优先级和一个响应优先级值。

常用分组2

抢占优先级高的可以中断嵌套,抢占优先级相同的多个中断源依据响应优先级依次执行

image.png

3.EXTI外部中断

功能:EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXtI中断程序

触发方式:上升沿\下降沿\双边沿\软件触发

支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断(PA0、PB0、PC0不能同时使用)

响应方式:中断响应/事件响应

中断响应是正常状态,事件响应不会触发中断,而是触发其他外设

注意:为了节省资源,EXTI将EXTI 5-9分配到同一通道中,EXTI 10-15分配到同一通道中,只会触发两个中断程序,编程时在这两个中断函数中要再根据标志位判断是哪个

4.AFIO复用IO引脚

  • AFIO主要用于引脚复用功能的选择和重定义

  • 在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择

5.代码

exti.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
	
void EXTIX_Init(void)
{

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟

//GPIO配置
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//Pin3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//配置为上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化

//EXTI配置
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource3);//引脚选择
EXTI_InitStructure.EXTI_Line=EXTI_Line3;//配置中断线
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//配置为中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //配置触发方式
EXTI_Init(&EXTI_InitStructure);

//NVIC配置
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置NVIC分组
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;//响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

void EXTI0_IRQHandler(void)
{
//中断函数
EXTI_ClearITPendingBit(EXTI_Line0);//清除标志位
}

////////如果需要判断标志位
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line14)==SET)
{
//中断函数
EXTI_ClearITPendingBit(EXTI_Line14); //清除标志位
}
}

exti.h

1
2
3
4
5
6
#ifndef __EXTI_H
#define __EXIT_H
#include "sys.h"
void EXTIX_Init(void); //外部中断初始化
#endif

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "exti.h"

int main(void)
{
delay_init();
EXTIX_Init();
while(1)
{
}
}