EXTI(外部中断)
1、EXTI简介
外部中断控制器,能够检测外部输入信号的变化边沿并由此产生中断。通过检测上升沿或者下降沿来产生中断源。
2、EXTI的内部结构
边沿检测检测到电平的跳变都会生成一个高脉冲信号,然后脉冲通过边沿选择传递到中断屏蔽,当中断屏蔽遇到脉冲时,打开开关,中断挂起有0->1,然后执行中断函数。【注】中断挂起需要手动置0。
2.1、EXTI通道
EXTI一共有20个通道,分别为EXTI0~EXTI19。而IO0连接着EXTI0通道,IO1连接着EXTI1通道,以此类推。让所有IO具备触发中断的能力
当然,如果GPIOA0使用了EXTI0时,GPIOB0~GPIOG0都不能使用EXTI0了,所以每个通过也就只能使用一个IO口。
2.2、内部寄存器
如图:除了软件触发寄存器外,其他的寄存器都是20位的,分别对应着20个EXTI通道。
- 当给上升沿寄存器的TR0写入1,给下降沿寄存器TR0写入0时,则EXTI0通道是上升沿产生一个中断源。如果都写入1,则上升沿和下降沿都能产生中断源。
- 中断屏蔽寄存器是开关,写入1关闭开关,写入0打卡开关
- 挂起寄存器,我们只需要手动置0,每次中断函数执行完成后,我们都应该给他置0,以便等待下一次中断
3、EXTI的编写程序
3.1、EXTI的编程接口
3.1.1、EXTI_Init
为什么不开启EXTI的时钟?因为啊默认都是打开了的。
4、编写实验
按钮通过外部中断控制LED灯的亮灭。下面是程序编写模型
其中AFIO用于选择IO引脚
c
/*按钮通过外部中断控制LED灯的亮灭。*/
#include "stm32f10x.h"
#include "stm32f10x_pal.h"
#include "OLED.h"
int main(void)
{
// PAL_Init();
// OLED_Init();
//1.PA0,PA1,PC13引脚的初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitTypeDef GPIOInitStruct;
GPIOInitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;//按钮
GPIOInitStruct.GPIO_Mode = GPIO_Mode_IPU;//配置为上拉输入
GPIO_Init(GPIOA ,&GPIOInitStruct);
GPIOInitStruct.GPIO_Pin = GPIO_Pin_13;//LED
GPIOInitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIOInitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//配置为开漏输出
GPIO_Init(GPIOC,&GPIOInitStruct);
//2.AFIO选择通道
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//选择EXTI0
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);//选择EXTI1
//3.对EXTI0,EXTI1通道进行配置
EXTI_InitTypeDef EXTIInitStruct;
EXTIInitStruct.EXTI_Line = EXTI_Line0;
EXTIInitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTIInitStruct.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿产生中断源
EXTIInitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTIInitStruct);
EXTIInitStruct.EXTI_Line = EXTI_Line1;
EXTIInitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTIInitStruct.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿产生中断源
EXTIInitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTIInitStruct);
//4.对NVIC进行配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVICInitStruct;
NVICInitStruct.NVIC_IRQChannel = EXTI0_IRQn;
NVICInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVICInitStruct.NVIC_IRQChannelSubPriority = 0;
NVICInitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVICInitStruct);
NVICInitStruct.NVIC_IRQChannel = EXTI1_IRQn;
NVICInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVICInitStruct.NVIC_IRQChannelSubPriority = 0;
NVICInitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVICInitStruct);
while(1)
{
}
}
//5.中断响应函数
void EXTI0_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line0);//清除中断状态
GPIO_WriteBit(GPIOC ,GPIO_Pin_13,Bit_RESET);//给ODR写入0,点亮LED
}
void EXTI1_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line1);//清除中断状态
GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);//熄灭LED
}