一、MCU中断程序执行过程
以MCU裸机程序框架为例,MCU 的主函数是个死循环:
主函数:
main(void)
{
While(1)
{
//主程序
}
}
如果没有中断或异常产生会一直在while(1)里执行主程序代码。当中断产生后,当前执行的任务会被打断,程序跳转到中断处理函数执行,执行完会返回之前的主程序断点处继续执行。
中断处理函数:
void IRQ_handler(void)
{
//中断处理程序
//清除中断标志,否则会不停的进入中断处理程序。
}
在中断处理函数中不要做复杂费时的事情,中断内做的事情尽可能少。
二、中断使用实例
STM32的IO都可以配置成外部中断,但不是同时都可以配成外部中断。需要遵循如下规则:
比如PA0设置成外部中断,PB0,PC0,PD0就不能配成外部中断。
比如PA1设置成外部中断,PB1,PC1,PD1就不能配成外部中断。
STM32的EXTI0-15中断线分配给IO使用。PA0的中断只能使用EXTI0的中断请求;PA1中断只能使用EXTI1的中断请求。
每个外部中断线可以独立的配置触发方式,包含上升沿,下降沿或者双边沿触发。每个中断可单独使能/屏蔽。
STM32的中断允许嵌套,抢占优先级高的可以打断抢占优先级低的中断执行。抢占优先级相同时,不能嵌套,不同响应优先级中断同时发生,优先级高的先执行。在程序设计时要根据具体情况分配好抢占优先级和响应优先级。
STM32的优先级分抢占和响应两种,具体选择哪种分组组合可以通过如下函数配置:
NVIC_PriorityGroupConfig()
优先级分组组合有5种:
第0组:所有4bit用于指定响应优先级;
第1组:最高1位用于指定抢占式优先级,后面3位用于指定响应优先级;
第2组:最高2位用于指定抢占式优先级,后面2位用于指定响应优先级;
第3组:最高3位用于指定抢占式优先级,后面1位用于指定响应优先级;
第4组:所有4位用于指定抢占式优先级。
以STM32为例,使用IO端口PB2的外部中断功能需要做如下初始化配置:
1 使能PB2的端口clock及复用功能clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
2 中断优先级初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//选择中断分组1
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQChannel; //选择中断通道2
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占中断优先级设置为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority =2; //响应中断优先级设置为2
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能中断
3 IO初始化
PIO_InitStructure.GPIO_Pin=GPIO_Pin_2; //选择引脚PB2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出频率最大50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;; //输入
GPIO_Init(GPIOB,&GPIO_InitStructure);
4 把PB2设置为外部中断模式
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource2);
EXTI_InitStructure.EXTI_Line = EXTI_Line2; //选择中断线路2
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //设置为中断请求 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //触发方式为上下降沿触发
EXTI_InitStructure.EXTI_LineCmd=ENABLE; //外部中断使能
EXTI_Init(&EXTI_InitStructure);
5 中断处理函数
void EXTI2_IRQHandler(void)
{
//处理程序
//清空中断标志位,防止连续进入中断
EXTI_ClearITPendingBit(EXTI_Line2);
}