今天来说下外部中断EXTI
其实外部中断和我们的定时器中断都差不多,只不过定时器中断是利用内部的计数器来进行定时,从而产生定时中断,而外部中断的触发条件是来自于外部,当外部的信息引起了外部中断,那么就会执行我们的外部中断服务函数。
在STM32F103中,每一个IO口都能够当做外部中断引脚,他们的对应关系为
PA0-PG0对应EXTI0
PA1-PG1对应EXTI1
…
PA15-PG15对应EXTI15
即所有端口的Pin_0对应着EXTI0,所有端口的Pin_1对应着EXTI1,依次类推
这个EXTI0—EXTI15我们叫做它外部中断线,同一时间内只能有一个IO口映射到外部中断线上面,即在同一时间内,PA0-PG0只能有一个引脚映射到EXTI0上面,但是各个中断线之间不受影响。同时,每一个外部中断线我们都可以单独配置它的触发方式(上升沿、下降沿、双边沿)
关于外部中断服务函数呢,它并没有0-15个中断服务函数,它只有7个,如下
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI5_9_IRQHandler
EXTI10_15_IRQHandler
即有几个外部中断线是共用一个外部中断服务函数的
然后我们来看一下外部中断初始化函数
初始化函数同样是配置一个结构体,结构体成员如下
typedef struct
{
uint32_t EXTI_Line; //指定要配置的中断线
EXTIMode_TypeDef EXTI_Mode; //模式:事件 OR中断
EXTITrigger_TypeDef EXTI_Trigger;//触发方式:上升沿/下降沿/双沿触发
FunctionalState EXTI_LineCmd; //使能 OR失能
}EXTI_InitTypeDef;
关于模式设置的事件和中断,我也不太清楚,百度了一下,不知道对不对
简单地说呢,从外部激励信号来看,中断和事件是没有区别滴;
但是,在芯片内部, 中断 会向CPU产生请求,由CPU去响应中断程序;
而 事件 则是对片内其他模块发出脉冲触发信号,具体其他设备怎么响应,就看这个模块自己怎么决定了
举个栗子
EXTI_InitStructure.EXTI_Line=EXTI_Line2;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
外部中断的一般配置步骤
1、初始化IO口为输入。
GPIO_Init();
2、开启IO口复用时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
3、设置IO口与中断线的映射关系。
void GPIO_EXTILineConfig();
4、初始化线上中断,设置触发条件等。
EXTI_Init();
5、配置中断分组(NVIC),并使能中断。
NVIC_Init();
6、编写中断服务函数。
EXTIx_IRQHandler();
7、清除中断标志位
EXTI_ClearITPendingBit();
部分代码
//外部中断4服务程序
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE4
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能复用功能时钟
//GPIOE.4 中断线以及中断初始化配置 下降沿触发 //KEY0
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
EXTI_InitStructure.EXTI_Line=EXTI_Line4;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn; //使能按键KEY0所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}
//外部中断4服务程序
void EXTI4_IRQHandler(void)
{
if(KEY0==0) //按键KEY0,KEY0需要进行宏定义
{
delay_ms(10);//按键消抖
if(KEY0==0)
{
LED0=!LED0;
LED1=!LED1;
}
}
EXTI_ClearITPendingBit(EXTI_Line4); //清除LINE4上的中断标志位
}
在上面这个栗子中,我是把按键的IO口,也就是PE4引脚给当成了外部中断输入引脚,当我们按下按键的时候,会有一个下降沿出现,这个下降沿就会触发我们已经配置好的外部中断,从而执行外部中断服务函数。