中断
中断
1. 理论知识
1.1 中断的概念
在主程序运行过程中,出现了特定事件,使得CPU暂停当前正在运行的程序,转而去处理这个事件,等这个事件处理完成之后,CPU再回到刚才被打断的位置继续处理,这就是中断。
打断CPU执行的特定事件,称为中断源。被中断源打断的位置称为断点。处理特定事件的过程,称为执行中断处理程序。

正在执行中断程序的时候,也能被另外一个中断源给中断,CPU转而去执行另外一个中断源的中断处理程序,这叫中断嵌套。通过优先级判断哪个中断先执行。
1.2 STM32的中断
1.2.1 中断数量和类型
Cortex-M3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。
但是,芯片厂商会对中断进行裁剪,STM32有84个中断,包含有16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级。STM32F103系列70个中断有10个内核中断和60个可编程的外部中断。可以参考芯片手册的9.1.2 中断和异常向量 章节

1.2.2 中断的体系结构
根据中断来源分为三类,1. 内核产生的中断,手册中也称其为异常 2.片上外设产生的中断 3. 外部中断即GPIO复用产生的中断。其中NVIC嵌套向量中断控制器和EXTI是控制中断的重难点。

1.2.3 NVIC嵌套向量中断控制器
NVIC(Nested vectored interrupt controller嵌套向量中断控制器)和处理器核的接口紧密相连,可以实现低延迟的中断处理和高效地处理中断。它管理所有的中断,决定哪个中断的处理给CPU执行。其中片上外设和内核中断是直接收到NVIC控制,外部中断要先经过EXTI控制(16个IO的中断与PVD(电源电压检测),RTC(实时时钟),USB,以太网检测共20个外部中断)
中断管理的逻辑:
给每个中断设置优先级。NVIC用4个位来控制优先级,值小的优先级高。把优先级分为两种:抢占优先级和响应优先级。
规则:
-
优先级值越小,优先级越高;
-
如果不设置优先级,则默认优先级为0;
-
先比较抢占优先级。抢占优先级高的可以打断抢占优先级低的;
-
若抢占优先级一样,再比较响应优先级。但是响应优先级不会导致中断嵌套;
-
若抢占优先级一样的同时挂起,则优先处理响应抢占优先级高的;
-
若挂起的优先级(抢占和响应)都一样,则查找中断向量表,值小的先响应。
在PRIGROUP寄存器中定义了优先级的设置模式,分配了抢占优先级和响应优先级的数量,如下图截于STM32F10xxx Cortex-M3编程手册:

即五种模式:
| 分组 | 抢占优先级 | 响应优先级 |
|---|---|---|
| 0 | 0位 取值范围:0 | 4位 取值范围:0-15 |
| 1 | 1位 取值范围:0-1 | 3位 取值范围:0-7 |
| 2 | 2位 取值范围:0-3 | 2位 取值范围:0-3 |
| 3 | 3位 取值范围:0-7 | 1位 取值范围:0-1 |
| 4 | 4位 取值范围:0-15 | 0位 取值范围:0 |
1.2.4 外部终端执行逻辑
如下图,外部中断的控制逻辑起始与输入线,1.通过上升沿或下降沿触发选择寄存器触发选择寄存器来检测外部的信号 2. 有检测到信号的话,进行或门判断,即可以软件触发也可以硬件触发 3.A位置有信号传入,请求挂起寄存器会自动硬件置位 4.中断屏蔽寄存器若关闭状态,即不做屏蔽,与门判断后,则传递至NVIC中断控制器。

2. 实践验证
2.1 寄存器方式
验证的硬件环境:stm32最小系统板+led灯+按键开关
实现逻辑:
配置相关时钟-》配置对应GPIO工作模式-》配置AFIO引脚复用的功能-》配置EXTI -》 配置NVIC
-
配置时钟,EXTI和NVIC时钟始终开启,无需手动开启

RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // 开启使用到的GPIO组时钟 RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // 开启开启AFIO引脚复用的时钟 -
配置GPIO工作模式和默认输出值


GPIOB->CRH &= ~GPIO_CRH_MODE11; GPIOB->CRH |= GPIO_CRH_MODE11_1; GPIOB->CRH &= ~GPIO_CRH_MODE11_0; GPIOB->ODR &= ~GPIO_ODR_ODR11; -
AFIO配置引脚复用选择

AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI11_PB; -
配置EXTI


EXTI->RTSR |= EXTI_RTSR_TR11; EXTI->IMR |= EXTI_IMR_MR11; -
配置NVIC
NVIC_SetPriorityGrouping(3); // 全部都是抢占优先级 NVIC_SetPriority(EXTI15_10_IRQn, 3); NVIC_EnableIRQ(EXTI15_10_IRQn); -
创建中断函数
void EXTI15_10_IRQHandler(void) { // 先清除中断挂起标志位 EXTI->PR |= EXTI_PR_PR10; // 防抖延迟 Delay_ms(10); // 判断如果依然保持高电平,就翻转LED_red if ((GPIOF->IDR & GPIO_IDR_IDR11) != 0) { LED_Toggle(LED_red); } }
2.2 库函数方式
实现逻辑:
cubmx配置对应功能引脚,在中断执行回调函数中实现想要的功能
-
配置相关引脚



-
在回调函数中实现想要的功能
/** * @brief GPIO外部中断回调函数 * @param GPIO_Pin: 指定的GPIO引脚,这里应该是外部中断触发的引脚号 * @retval 无 * * 该函数在GPIO_PIN_11(即PA11)上的外部中断事件触发时被调用。 * 它的主要目的是在检测到PA11引脚状态为高电平时,切换PB15引脚的输出状态。 * 为了防止外部中断的误触发,在切换PB15引脚状态前,加入了一段15毫秒的延时。 */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == GPIO_PIN_11) { HAL_Delay(15); if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11) == GPIO_PIN_SET) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_15); } } }

浙公网安备 33010602011771号