一.中断的定义:
对于单片机来说,中断是指CPU正在处理某个事件A,发生了另一件事件B,请求CPU迅速去处理(中断发生);CPU暂时停止当前的工作(中断响应),转去处理事件B(中断服务);待CPU处理事件B完成后,再回到原来的事件A(断点)继续执行,这一过程称之为中断。
中断的作用和意义:
1.实时控制:在确定的时间内对相应事件做出相应;例如:温度控制;
2.故障处理:检测到故障,需要第一时间进行处理;
3.数据传输:不确定数据何时会来,利用中断进行控制;
中断的作用:高效处理紧急程序,并且不会占用CPU资源。
二、 NVIC
2.1 NVIC基本概念
NVIC 即嵌套向量中断控制器,全称 Nested vectored interrupt controller。属于是内核的器件,其作用是对STM32中的中断进行管理,因为M3内核中的中断数量很多,当同时出现多个中断时,优先处理哪个中断?以及那些中断不处理等,都要靠NVIC 进行控制。M3 内核都是支持 256 个中断,其中包含了 16 个系统中断和 240 个外部中断,并且具有 256 级的可编程中断设置。
NVIC支持:256个中断(16个内核+240个外部);支持256个优先级。
三 STM32中断优先级基本概念:
1、抢占优先级(pre):高抢占优先级可以打断正在执行的低抢占优先级中断;
2、响应优先级(sub):当抢占优先级相同时,响应优先级高的先执行,但是不能相互打断;
3、抢占优先级和响应优先级都相同的情况下,自然优先级越高的先执行;
4、自然优先级:中断向量表中的优先级;
5、数值越小,表示优先级越高;
四 NVIC使用(STM32)
使用步骤:
1、设置中断分组:AIRCR寄存器[10:8];
HAL_NVIC_SetPriorityGrouping();
2、设置中断优先级:IPR寄存器[7:4];
HAL_NVIC_SetPriority();
3、使能中断:ISER寄存器;
HAL_NVIC_EnableIRQ();
五 EXIT(外部中断控制)
1 EXIT基本概念
全称:外部中断事件控制器
包含20个产生事件/中断请求的边沿检测器,即20条EXIT线;
中断和事件的理解
中断:要进入NVIC,有相应的中断服务函数,需要CPU处理;
事件:不进入NVIC,仅用内部硬件自动控制,TIM,DMA,ADC等
EXIT线说明:
0-15:对应GPIO_PIN 0-15中断;
16:PVD输出;
17:RTC闹钟事件;
18:USB唤醒事件;
19:连接到以太网唤醒事件(只适用于互联型产品)
每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。
2EXIT的配置步骤
1、使能GPIO时钟;
2、设置GPIO的工作模式;(上拉、下拉、浮空输入)
3、使能AFIO时钟;(设置AFIO时钟,开启相关寄存器);
4、设置GPIO与EXIT映射关系;(选择IO对应EXIT输入线,AFIO_EXICR寄存器);
5、设置EXIT屏蔽、上升沿、下降沿;(设置EXIT对应通道的屏蔽和上升沿、下降沿触发,EMR、RTSR、FTSR寄存器);
6、设置NVIC,分3步(优先级分组、优先级以及使能);
7、设置中断服务函数(包括清除中断标志);
六 实例分析
通过按键中断控制led灯的亮灭。
配置过程及代码分析:
将PA0管脚设置为EXTI0然后将优先级分组降下一点。
管脚配置代码分析:
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10, GPIO_PIN_SET);
/*Configure GPIO pin : PE2 */
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/*Configure GPIO pins : PF8 PF9 PF10 */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/*Configure GPIO pin : PA0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 2);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
前面和之前一样配置四个led灯io口的信息,后边配置PA0的模式为具有下降边缘触发检测的外部中断模式。EXTI初始化,设置抢占优先级和响应优先级为2,2 使能EXTI0。
中断函数实现:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin==GPIO_PIN_0)
{
printf("key int ");
HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10);
HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_2);
}
在按键按下时打印一句话并且翻转io口状态。
实现结果:
刚上电时,led不亮。
按下按键后串口打印
同时,led一起亮。
实现完成