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结构体
- EXTI_Line:EXTI 中断/事件线选择,可选 EXTI0 至 EXTI19。
- EXTI_Mode:EXTI 模式选择,可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。
- EXTI_Trigger:EXTI 边沿触发事件,可选:
上升沿触发(EXTI_Trigger_Rising)、
下降沿触发 ( EXTI_Trigger_Falling) 、
上升沿和下降沿都触发( EXTI_Trigger_Rising_Falling)。 - 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 配置为浮空输入,由外部电路完全决定引脚的状态。
中断向量表
优先级 | 名称 | 说明 | 地址 |
---|---|---|---|
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 |