1.中断介绍
1.1中断概念
* CPU执行程序时,由于发生了某种随机的事件(外部或内部),引起CPU暂时中断正在运行的程序,
转去执行一段特殊的服务程序(中断服务子程序或中断处理程序),以处理该事件,该事件处理完后又返回被中断的程序
继续执行,这一过程称为中断。
* 引发中断的称为中断源。比如:玩游戏时突然门铃响,那么门铃响就相当于中断源。
* 有些中断还能够被其他高优先级的中断所中断,那么这种情况又叫做中断的嵌套。
![中断示意图](https://img2018.cnblogs.com/blog/1477983/201911/1477983-20191112135438875-1587798570.png)
##1.2中断优先级
中断优先级的一个意义:出现多个中断同时触发,但是不能同时处理,所以先后顺序之分,要根据实际上的运行环境优先处理重要的中断。
* 1.概述
STM32 对中断优先级进行分组,共 5 组,组 0~4,这些分组是用于指定当前M4支持多少个抢占优先级和多少个响应优先。
同时,对每个中断设置一个抢占优先级和一个响应优先级。函数原型如下:
```
/**
* @brief Configures the priority grouping: pre-emption priority and subpriority.
* @param NVIC_PriorityGroup: specifies the priority grouping bits length.
* This parameter can be one of the following values:
* @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority //不支持抢占优先级
* 4 bits for subpriority //支持16个响应优先级
* @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority //支持2个抢占优先级
* 3 bits for subpriority //支持8个响应优先级
* @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority //支持4个抢占优先级
* 2 bits for subpriority //支持4个响应优先级
* @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority //支持8个抢占优先级
* 1 bits for subpriority //支持2个响应优先级
* @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority //支持16个抢占优先级
* 0 bits for subpriority //不支持响应优先级
* @note When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible.
* The pending IRQ priority will be managed only by the subpriority.
* @retval None
*/
void NVIC_PriorityGroupConfig(uint32_t, NVIC_PriorityGroup)
```
* 2.中断优先级分组图片
* 注意:优先级分组,只要开机初始化一次就可以了(在运行中调整优先级分组,不推荐做)
- 3.抢占优先级与响应优先级区别
- 1)高抢占优先级是可以打断正在进行的低抢占优先级的中断。抢占优先级若相同,则不会出现抢占的过程。
- 2)抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。
- 3)抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。
- 4)抢占优先级相同且响应优先级相同的中断,假如同时发生,会按照硬件内部固定的优先级执行,参考STM32F4xx参考手册的中断向量表。
- 5)无论是抢占优先级还是响应优先级,优先级数值越小,就代表优先级越高。
#2.外部中断
* 外部中断/事件控制器包含多达 23 个用于产生事件/中断请求的边沿检测器。
* 每根输入线都可单独进行配置,以选择类型(中断或事件)和相应的触发事件(上升沿触发、下降沿触发或边沿触发)。
* 每根输入线还可单独屏蔽。
* 挂起寄存器用于保持中断请求的状态线
2.1外部中断配置
void EXTILine_Config(void)
{
//1) 创建初始化结构体
//创建外部中断初始化结构体
EXTI_InitTypeDef EXTI_InitStructure;
//创建GPIO初始化结构体
GPIO_InitTypeDef GPIO_InitStructure;
//创建NVIC初始化结构体
NVIC_InitTypeDef NVIC_InitStructure;
//2) Enable GPIOA clock
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//3) Enable SYSCFG clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
//4) Configure PA0 pin as input floating
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//5) Connect EXTI Line0 to PA0 pin
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
//6) Configure EXTI Line0
EXTI_InitStructure.EXTI_Line = EXTI_Line0 ;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
//设置外部中断触发方式:下降沿触发
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
//7) 中断优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//8) Enable and set EXTI Line0 Interrupt priority
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
2.2中断处理函数
void EXTI0_IRQHandler(void)
{
//Checks whether the specified EXTI line is asserted or not
//发生了中断
if(!EXTI_GetITStatus(EXTI_Line0) == RESET)
{
/* Toggle LED0 */
LED0 = 0;
/* Clear the EXTI line 0 pending bit */
EXTI_ClearITPendingBit(EXTI_Line0);
}
}