由外部设备发起的中断请求,会使得设备暂停当前的主程序,保存标志位并把当前指令压入堆栈,转而去执行中断的子程序。执行完毕后再弹出执行堆栈,恢复标志位,继续执行主程序。
STM32的每个IO都可以作为外部中断输入。
STM32的中断控制器支持19个外部中断/事件请求:
线0~15:对应外部IO口的输入中断 PAx~PIx。
线16:连接到PVD输出。
线17:连接到RTC闹钟事件。
线18:连接到USB唤醒事件。
每个外部中断线可以独立的配置触发方式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专用的状态位。
这时候想必读者可能要问了,STM32供IO使用的中断线只有16个,但是STM32F10x系列的IO口多达上百个,STM32F103ZET6(112),STM32F103RCT6(51),那么中断线怎么跟IO口对应上呢?下图就是STM32的外部中断线和IO口的对应关系:

对于每个中断线,我们可以设置相应的触发方式(上升沿触发,下降沿触发,边沿触发)以及使能。
是不是16个中断线就可以分配16个中断服务函数呢?
IO口外部中断在中断向量表中只分配了7个中断向量,也就是只能使用7个中断服务函数

从表中可以看出,外部中断线5~9分配一个中断向量,共用一个服务函数。
外部中断线10~15分配一个中断向量,共用一个中断服务函数。
下面是中断服务函数列表:
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler
//中断初始化配置函数
void EXTI_Init(void)
{GPIO_InitTypeDef GPIO_Initure;__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟GPIO_Initure.Pin=GPIO_PIN_0; //PA0GPIO_Initure.Mode=GPIO_MODE_IT_RISING; //上升沿触发GPIO_Initure.Pull=GPIO_PULLDOWN; //下拉电阻HAL_GPIO_Init(GPIOA,&GPIO_Initure);//中断线0-PA0HAL_NVIC_SetPriority(EXTI0_IRQn,2,0); //抢占优先级为2,子优先级为0HAL_NVIC_EnableIRQ(EXTI0_IRQn); //使能中断线0; //使能中断线13
}
在 HAL 库中,中断处理初始化和 GPIO 初始化使用同一个结构体,如果想把他当作一个初始化中断结构体,只需为 GPIO_Initure.Mode= 赋值,HAL库即会把他当作一个中断来看待。在此时我们设置的是上升沿触发,也就是从低电平转到高电平时刻触发这个中断。
//中断服务函数
void EXTI0_IRQHandler(void)
{HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);//调用中断处理公用函数
}//中断服务回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{//这里写中断程序switch(GPIO_Pin){case GPIO_PIN_0://GPIO0的中断程序break;case GPIO_PIN_13://GPIO13中断程序break;}
}
首先,当 EXTI0 有中断事件后,HAL 库会帮我们调用 EXTI0_IRQHandler() 这个函数,如果是 EXTIx 就以此类推。
之后我们需要在这个函数中调用 HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0),他会帮我们调用
void HAL_GPIO_EXTI_Callback() 这个函数,在这个函数中就可以写我们的中断子程序了。这个流程是较为规范的,请不要省略其中的步骤。
#include "sys.h"
#include "delay.h"
#include "led.h"//中断初始化配置函数
void EXTI_Init(void)
{GPIO_InitTypeDef GPIO_Initure;__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟GPIO_Initure.Pin=GPIO_PIN_0; //PA0GPIO_Initure.Mode=GPIO_MODE_IT_RISING; //上升沿触发GPIO_Initure.Pull=GPIO_PULLDOWN; //下拉电阻HAL_GPIO_Init(GPIOA,&GPIO_Initure);//中断线0-PA0HAL_NVIC_SetPriority(EXTI0_IRQn,2,0); //抢占优先级为2,子优先级为0HAL_NVIC_EnableIRQ(EXTI0_IRQn); //使能中断线0; //使能中断线13
}//中断服务函数
void EXTI0_IRQHandler(void)
{HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);//调用中断处理公用函数
}//中断服务回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{//这里写中断程序switch(GPIO_Pin){case GPIO_PIN_0://GPIO0的中断程序break;case GPIO_PIN_13://GPIO13中断程序break;}
}int main(void)
{HAL_Init(); //初始化HAL库 Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhzdelay_init(180); //初始化延时函数LED_Init(); //初始化LED EXTI_Init(); //外部中断初始化while(1){delay_ms(1000); //务必始终循环延迟,否则执行完程序就不相应中断了}
}
上一篇:我应该是懂居家办公的吧?
下一篇:CF思维训练