上期我们学习了GPIO驱动数码管/蜂鸣器/LED和按键等外设,本期我们一起来学习STM32中断的相关内容
什么是中断?
当CPU正在处理某个事件的时候,外界发生了紧急事件请求,CPU需要暂停当前的工作,转而去处理这个紧急事件,处理完之后,再次回到之前被中断的地方,继续执行原来的工作,这样的过程就叫做中断。
具体内容可以去看 “蓝桥杯单片机学习5——外部中断” ,我有详细的介绍过!
中断的意义
中断的意义:高效处理紧急程序,不会一直占用CPU资源
GPIO外部中断的中断简图
在51单片机的学习中,我们了解过外部中断的相关概念,在STM32中,我们也有外部中断的概念
不同于51单片机,要实现一个完整的外部中断,需要经历图上的四个步骤,下面我将详细的介绍每一个环节,首先我们从NVIC开始。
NVIC
什么是NVIC?
NVIC:Nested vectored interrupt controller,中文名称:嵌套向量中断控制器,属于内核(M3/4/7),最多可支持对256种(16个内核中断和240个外部中断)中断的控制,可设置256个中断优先级,允许厂商根据产品需要对其进行裁剪。
在我们的NANO板子中,使用了62个中断(10个内核中断+52个外部中断),最多支持16个优先级(使用4位中断优先级),
中断向量表
中断向量表就是在内存中定义了一段空间,以四字节对齐的方式,按照中断编号顺序存放每一个中断服务函数的首地址。
中断向量表定义在启动文件,当发生中断,CPU会判断中断源,通过中断向量表进入到对应的中断服务函数中。
以下是NANO板的中断向量表全部内容,在STM32F411参考手册的201~203页
代码
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window WatchDog
DCD PVD_IRQHandler ; PVD through EXTI Line detection
DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line
DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line
DCD FLASH_IRQHandler ; FLASH
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line0
DCD EXTI1_IRQHandler ; EXTI Line1
DCD EXTI2_IRQHandler ; EXTI Line2
DCD EXTI3_IRQHandler ; EXTI Line3
DCD EXTI4_IRQHandler ; EXTI Line4
DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0
DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1
DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2
DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3
DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4
DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5
DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6
DCD ADC_IRQHandler ; ADC1, ADC2 and ADC3s
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD EXTI9_5_IRQHandler ; External Line[9:5]s
DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9
DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10
DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD 0 ; Reserved
DCD EXTI15_10_IRQHandler ; External Line[15:10]s
DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line
DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7
DCD 0 ; Reserved
DCD SDIO_IRQHandler ; SDIO
DCD TIM5_IRQHandler ; TIM5
DCD SPI3_IRQHandler ; SPI3
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0
DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1
DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2
DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3
DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD OTG_FS_IRQHandler ; USB OTG FS
DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5
DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6
DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7
DCD USART6_IRQHandler ; USART6
DCD I2C3_EV_IRQHandler ; I2C3 event
DCD I2C3_ER_IRQHandler ; I2C3 error
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD FPU_IRQHandler ; FPU
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SPI4_IRQHandler ; SPI4
DCD SPI5_IRQHandler ; SPI5
__Vectors_End
NVIC寄存器
NVIC的相关寄存器主要包括以下几个:
寄存器 | 有效位数 | 数量 | 功能 |
---|---|---|---|
中断使能寄存器(ISER) | 32 | 8 | 每一个位控制一个中断使能 |
中断除能寄存器(ICER) | 32 | 8 | 每一个位控制一个中断除能 |
中断挂起寄存器(ISPR) | 32 | 8 | 每一个位控制一个中断挂起 |
中断解挂寄存器(ICPR) | 32 | 8 | 每一个位控制一个中断解挂 |
中断活动位寄存器(IABP) | 32 | 8 | 只读寄存器,每一个位对应一个中断的状态 |
中断优先级寄存器(IPR) | [7:4] | 240 | 每一个寄存器对应一个中断的优先级 |
软件触发中断寄存器(STIR) | 8 | 1 | 写入0~239,可直接触发对应中断 |
应用程序中断及复位控制寄存器(AIRCR) | [10:8] | 1 | 设置中断优先级分组 |
中断使能寄存器:Interrupt set-enable registers (NVIC_ISERx)
一共有8个这样的中断使能寄存器(8*32 = 256),可控制256个中断的使能,在对应位写入1可以使能对应的中断。
中断除能寄存器:Interrupt clear-enable registers (NVIC_ICERx)
同样有8个这样的寄存器,功能与上面相反。
中断挂起寄存器:Interrupt set-pending registers (NVIC_ISPRx)
当产生了一个中断请求,但是CPU无法响应时(比如CPU在执行优先级更高的中断),中断挂起寄存器的对应位会被置1,知道中断执行相应的中断服务函数后清零(也可以手动清零,通过中断解挂寄存器)。
有八个这样的寄存器,分别控制每一个中断的挂起。写入1时,挂起对应中断。
中断解挂寄存器:Interrupt clear-pending registers (NVIC_ICPRx)
有挂起寄存器,那么对应的就会有解挂寄存器。
有八个这样的寄存器,分别控制每一个中断的解挂。写入1时,解挂对应中断。
中断活动位寄存器:Interrupt active bit registers (NVIC_IABRx)
有8个这样的寄存器,为只读寄存器,如果某中断正在被执行或者被挂起则对应位为1,否则为0。通过这个寄存器我们可以便捷的观察每个中断的状态。
中断优先级寄存器:Interrupt priority registers (NVIC_IPRx)
在STM32中一共有240个这样的寄存器。分别用来设置240个外部中断的优先级,每个寄存器的低八位用来设置优先级,其他位保留。前面提到过,我们的NANO板最多支持16个优先级设置,是因为NANO板中只用到了低八位中的[7:4]。其它的[3:0]保留,不做使用。
软件触发中断寄存器:Software trigger interrupt register (NVIC_STIR)
这个寄存器很神奇,可以控制外部中断由软件触发,在寄存器的低八位写入0~239可以控制中断号为0 ~ 239的外部中断触发,进入中断服务函数。
应用程序中断及复位控制寄存器:Application interrupt and reset control register (AIRCR)
这个寄存器不在NVIC的相关寄存器之中,但是关系到NVIC的中断优先级分组,所以我们需要了解。其位[10:8]控制NVIC的中断优先级分组。
需要注意的是,要对该寄存器实现写入,那必须在写入的同时对高16位写入0x5FA,否则写入会失败。
其他的位这里不做过多介绍。
NVIC工作原理
以上是NVIC的具体中作原理,其中:
- 我们可以人为的控制外部中断的使能或失能,通过对不同中断的优先级及分组进行设置,控制CPU在面对多个中断时的相应顺序。
- 内核中断也叫NMI(不可屏蔽中断,优先级大于外部中断),可直接被CPU响应。
STM32中断优先级概念:
1,抢占优先级(pre):高抢占优先级可以打断正在执行的低抢占优先级中断
2,响应优先级(sub):当抢占优先级相同时,响应优先级高的先执行,但是不能互相打断
3,抢占和响应都相同的情况下,自然优先级越高的,先执行
4,自然优先级:中断向量表的优先级
5,数值越小,表示优先级越高
中断优先级分组
在NANO板中一个由五种优先级分组,具体如下:
特别提示:一个工程中,一般只设置一次中断优先级分组。如果进行了多次优先级分组,则以最后一次设置的为准。
NVIC的使用
以上就是NVIC的全部内容,下面我们来学习EXTI的相关内容
EXTI
EXTI基本概念
External(Extended) interrupt/event Controller,外部(扩展)中断事件控制器
外部中断/事件控制器包含多达 23 个用于产生事件/中断请求的边沿检测器。每根输入线都可 单独进行配置,以选择类型(中断或事件)和相应的触发事件(上升沿触发、下降沿触发或边沿触发)。每根输入线还可单独屏蔽。挂起寄存器用于保持中断请求的状态线。
其中0 ~ 15的EXTI线分别对应GPIO0 ~ 15外部中断,其他的EXTI线与事件对应关系如下:
主要特性
F1/F4/F7系列
每条EXTI线都可以单独配置:选择类型(中断或者事件)、触发方式(上升沿,下降沿或者双边沿触发)、支持软件触发、开启/屏蔽、有挂起状态位
H7系列
由其它外设对 EXTI 产生的事件分为可配置事件和直接事件。
可配置事件:简单概括,基本和F1/F4/F7系列类似
直接事件:固定上升沿触发、不支持软件触发、无挂起状态位(由其它外设提供)
中断和事件的理解:
中断:要进入NVIC,有相应的中断服务函数,需要CPU处理
事件:不进入NVIC,仅用于内部硬件自动控制的,如:TIM、DMA、ADC
EXTI工作原理
要了解EXTI的工作原理,我们首先要了解以下EXTI的相关寄存器。
中断屏蔽寄存器:Interrupt mask register (EXTI_IMR)
对应位为0时屏蔽对应EXTI线上的中断请求。为1时开放对应EXTI线上的中断请求。
注意:
- EXTI 线 19 连接到以太网唤醒事件
- EXTI 线 20 连接到 USB OTG HS(在 FS 中配置)唤醒事件
由于我们的NANO不是互联型的开发板,所以不存在这两个EXTI线。默认保留[20:19]
事件屏蔽寄存器:Event mask register (EXTI_EMR)
对应位为0时屏蔽对应EXTI线上的事件请求。为1时开放对应EXTI线上的事件请求。
上升沿触发选择寄存器:Rising trigger selection register (EXTI_RTSR)
对应位为0表示该中断/事件上升沿不触发,为1则表示该中断/事件上升沿触发
下降沿触发选择寄存器:Falling trigger selection register (EXTI_FTSR)
对应位为0表示该中断/事件下降沿不触发,为1则表示该中断/事件下降沿触发
软件中断事件寄存器:Software interrupt event register (EXTI_SWIER)
对应位写入1可以将请求挂起寄存器EXTI_PD对应位置1,产生中断请求。
通过清除 EXTI_PR 的对应位(写入“1”),可以清除该位为“0”。
请求挂起寄存器:Pending register (EXTI_PR)
对应位为1表示产生了中断请求
当在外部中断线上发生了选择的边沿事件,该位被置“1”。在此位中写入“1”可以清除它,也可以通过改变边沿检测的极性清除
以上就是EXTI的所有相关寄存器,下面我们来了解一下EXTI的具体工作原理:
当外部输入线有信号进来或者软件中断事件寄存器对应为被置1时,边沿检测电路会对其进行检测,如果为对应的信号沿则相关信号触发沿选择寄存器对应位被置1,后通过中断/事件屏蔽寄存器选择,时产生中断还是产生信号,还是都不产生。
EXTI与IO映射关系
SYSCFG简介(F4/F7/H7)
System configuration controller,即系统配置控制器,用于外部中断映射配置等
通过寄存器SYSCFG_EXTICR1 ~ 4,配置EXTI中断线0~15对应具体哪个IO口。
具体配置方法如下:
举个栗子:
SYSCFG_EXTICR1[11:8] = 0010 代表将PC2端口设置为外部中断模式。
EXTI和IO映射关系
另外七根 EXTI 线连接方式如下:
● EXTI 线 16 连接到 PVD 输出
● EXTI 线 17 连接到 RTC 闹钟事件
● EXTI 线 18 连接到 USB OTG FS 唤醒事件
● 不连
● 不连
● EXTI 线 21 连接到 RTC 入侵和时间戳事件
● EXTI 线 22 连接到 RTC 唤醒事件
中断使用方法
以上时EXTI的使用方法图解,下面为具体的流程:
在使用HAL库开发的过程中则只需要进行以下步骤
在STM32中EXTI5 ~ 9 共用一个中断服务函数,EXTI10 ~ 15 共用一个中断服务函数。
中断驱动方式
HAL库中断回调处理机制
在使用HAL库开发时,当断触发进入中断服务函数后,首先会调用HAL中断处理公用函数,负责清除对应的中断标志位,后调用中断回调函数,实现对不同中断源的处理。
实战1——外部中断控制LED亮灭
前面我们讲了一系列中断的相关内容,下面,我们来尝试以下通过外部中断,来控制LED亮灭。
任务要求
- 通过按键控制LED的亮灭,当按键按下时,LED的状态翻转
- 通过按键控制蜂鸣器的开关,
- 当蜂鸣器打开时,LED7亮起,否则熄灭
具体按键与功能关系如下:
按键 | 功能 |
---|---|
WKUP | 蜂鸣器开启,LED0状态翻转 |
KEY0 | 蜂鸣器关闭,LED1状态翻转 |
KEY1 | LED2状态翻转 |
KEY2 | LED3状态翻转 |
蜂鸣器开启 | LED7打开,否则关闭 |
CubeMX配置
总体概览
端口配置
1 . WKUP配置
2.KEYX配置
3. LED/蜂鸣器配置
请参照: “ 夜深人静学32系列9——GPIO驱动数码管/蜂鸣器/按键/LED ”,这里不做介绍
4.NVIC配置
代码实现
1.中断服务函数
void EXTI0_IRQHandler(void)
{
/* USER CODE BEGIN EXTI0_IRQn 0 */
/* USER CODE END EXTI0_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(WKUP_Pin);
/* USER CODE BEGIN EXTI0_IRQn 1 */
/* USER CODE END EXTI0_IRQn 1 */
}
/**
* @brief This function handles EXTI line2 interrupt.
*/
void EXTI2_IRQHandler(void)
{
/* USER CODE BEGIN EXTI2_IRQn 0 */
/* USER CODE END EXTI2_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(KEY2_Pin);
/* USER CODE BEGIN EXTI2_IRQn 1 */
/* USER CODE END EXTI2_IRQn 1 */
}
/**
* @brief This function handles EXTI line[9:5] interrupts.
*/
void EXTI9_5_IRQHandler(void)
{
/* USER CODE BEGIN EXTI9_5_IRQn 0 */
/* USER CODE END EXTI9_5_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(KEY0_Pin);
HAL_GPIO_EXTI_IRQHandler(KEY1_Pin);
/* USER CODE BEGIN EXTI9_5_IRQn 1 */
/* USER CODE END EXTI9_5_IRQn 1 */
}
2.HAL库中断公用处理函数
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET) //确认以及触发中断
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); //清除中断标志位
HAL_GPIO_EXTI_Callback(GPIO_Pin); //调用中断回调函数
}
}
3.中断回调函数
//数据处理回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == WKUP_Pin ) //判断中断源为WKUP中断
{
HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin); //改变LED0的状态
HAL_GPIO_WritePin(BEEP_GPIO_Port,BEEP_Pin,GPIO_PIN_RESET); //打开蜂鸣器
}
if(GPIO_Pin == KEY0_Pin) //判断中断源为KWY0中断
{
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin); //改变LED1状态
HAL_GPIO_WritePin(BEEP_GPIO_Port,BEEP_Pin,GPIO_PIN_SET); //关闭蜂鸣器
}
if(GPIO_Pin == KEY1_Pin ) //判断中断源为KWY1中断
{
HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin); //改变LED2状态
}
if(GPIO_Pin == KEY2_Pin) //判断中断源为KWY2中断
{
HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin); //改变LED3状态
}
if(HAL_GPIO_ReadPin(BEEP_GPIO_Port,BEEP_Pin) == 1) //蜂鸣器开启,打开LED7
{
HAL_GPIO_WritePin(LED7_GPIO_Port,LED7_Pin,GPIO_PIN_SET);
}
if(HAL_GPIO_ReadPin(BEEP_GPIO_Port,BEEP_Pin) == 0) //蜂鸣器关闭,关闭LED7
{
HAL_GPIO_WritePin(LED7_GPIO_Port,LED7_Pin,GPIO_PIN_RESET);
}
}
以上就是本次实战用到的所有代码…………
总结
中断的理论知识相当多,需要全部理解存在一定难度,但是使用CubeMX生成代码,会显得尤为简单,不过我们还是需要理解GPIO中断的相关内容,使用起来才会更加简单。文章来源:https://www.toymoban.com/news/detail-793697.html
本篇内容较多,制作不易,点个赞吧…………文章来源地址https://www.toymoban.com/news/detail-793697.html
到了这里,关于夜深人静学32系列10——GPIO中断/NVIC/EXTI/SYSCFG详解,外部中断控制LED的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!