03.外部中断
实验说明
本系列实验都是基于STM32F1的单片机进行的编程实验。
实验简介¶
这里使用单片机的PB5口来实现单片机的外部中断。
中断简介¶
先简单介绍一下中断的概念,在 STM32 中,对信号的处理可以分为轮询方式和中断方式,轮询方式就是不断去访问一个信号的端口,看看有没有信号进入,有则进行处理,中断方式则是当输入产生的时候,产生一个触发信号告诉 STM32 有输入信号进入,需要进行处理。
中断的流程就是,先初始化一个条件,这个条件可以是引脚检测到下降沿,可以是你定的一个倒计时,或者其他条件,你的程序正在顺序执行中,一旦这个条件满足了,他就会暂停当前执行的程序,去执行中断服务函数里面的程序,当中断服务函数的程序执行完了后,又返回之前正在执行的程序。
代码实现¶
我们这里的中断,他的中断条件就是引脚发生了边沿变换,就像下面
上升沿中断:当 GPIO 的电平从低电平跳变成高电平时,引发外部中断。
下降沿中断:当 GPIO 的电平从高电平跳变成低电平时,引发外部中断。
外部中断的配置流程为 初始化引脚 ->打开复用时钟->初始化外部中断条件->初始化中断优先级
void bsp_exti_init()
{
//打开时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//引脚初始化
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB,&GPIO_InitStruct);
}
//中断线初始化
{
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
//初始化中断线
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5);
}
//NVIC初始化
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //使能外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
}
}
中断线初始化中,初始化了这个中断触发的条件,比如按键WK_UP,他是PA0,对应的中断线就是0,然后因为他按下按键是由低到高,所以就是上升沿触发中断EXTI_Trigger_Rising,最后,再使用GPIO_EXTILineConfig函数将对应的引脚,和中断线对起来,一根线只能有一个中断源,EXTI_Line0只能和PA0,PB0,PC0,PD0等0号引脚相连,当他和PA0相映射后,就不能和PB0相映射了,其他的引脚同理。
NVIC初始化,是在初始化这个中断的优先级,当两个条件同时满足的时候,中断优先级高的执行,关于中断通道EXTI04有自己独立的,59共用一个,10~15共用一个,优先级先比较抢占优先级,再比较子优先级,数字越小优先级越高,关于等级大小有5种分配,如下
| 配置方式 | 抢占优先级 | 子优先级 |
|---|---|---|
| NVIC_PriorityGroup_0 | 0 | 0~15 |
| NVIC_PriorityGroup_1 | 0~1 | 0~7 |
| NVIC_PriorityGroup_2 | 0~3 | 0~3 |
| NVIC_PriorityGroup_3 | 0~7 | 0~1 |
| NVIC_PriorityGroup_4 | 0~15 | 0 |
这个分配,一般在main函数最前方,通过NVIC_PriorityGroupConfig函数初始化。
关于中断通道,0、1、2、3、4有自己的单独的中断通道,EXTI0_IRQn和EXTI1_IRQn和EXTI2_IRQn和EXTI3_IRQn和EXTI4_IRQn,然后59公用一个中断通道EXTI9_5_IRQn,1015公用一个中断通道EXTI15_10_IRQn
中断初始化配置完成后,就要写中断服务函数了,中断服务函数,可以写在工程任何位置,但是该函数各个中断通道都各自只能有一个,而且函数名固定。
0、1、2、3、4有自己的单独的中断服务函数,EXTI0_IRQHandler和EXTI1_IRQHandler和EXTI2_IRQHandler和EXTI3_IRQHandler和EXTI4_IRQHandler,然后59公用一个中断服务函数EXTI9_5_IRQHandler,1015公用一个中断服务函数EXTI15_10_IRQHandler
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line5) == SET)
{
led0_on();
}
EXTI_ClearITPendingBit(EXTI_Line5);
}
当对应通道的中断源触发的时候,就会进入对应的通道服务函数,记得在退出中断服务函数的时候要清除中断标志位,不清除就可能一直进入中断。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请附上原文出处链接及本声明。