STM32 NVIC中断控制器
- NVIC基本概念
- NVIC简介
-
NVIC是Nested Vectored Interrupt Controller(嵌套向量中断控制器)的缩写。它是ARM Cortex - M系列处理器(如STM32所采用的内核)中的一个重要组成部分,用于管理中断。
-
在STM32微控制器中,NVIC主要负责中断的优先级分配、中断的使能和禁止、中断的挂起和解除挂起等操作。它使得STM32能够高效地处理多个中断请求。
- 中断优先级
-
NVIC支持中断优先级的设置。STM32的中断优先级分为抢占优先级和子优先级。
-
抢占优先级:当有高抢占优先级的中断到来时,它可以打断正在执行的低抢占优先级的中断。例如,抢占优先级为1的中断可以打断抢占优先级为2的中断。抢占优先级的数值越小,优先级越高。
-
子优先级:当有多个抢占优先级相同的中断同时到来时,子优先级起作用。子优先级的数值越小,优先级越高。例如,抢占优先级都是1的两个中断,子优先级为0的中断会先于子优先级为1的中断被响应。
-
在STM32中,中断优先级的配置是通过NVIC的优先级寄存器来设置的。不同的STM32型号,其可配置的优先级位数可能不同。例如,STM32F103系列支持4位优先级配置,可以分为抢占优先级和子优先级的组合,如2位抢占优先级和2位子优先级等。
- 中断使能和禁止
-
NVIC可以通过使能寄存器(ISER)来使能中断。当一个中断被使能后,当该中断源有请求信号到来时,NVIC就会按照优先级等规则进行处理。
-
同样,通过禁止寄存器(ICER)可以禁止中断。禁止中断后,即使该中断源有请求,NVIC也不会响应。这在某些情况下很有用,比如在调试过程中或者当需要暂时屏蔽某些中断以防止干扰时。
- 中断挂起和解除挂起
-
中断挂起是指当一个中断正在执行,但是由于更高优先级的中断到来,当前中断被暂时中断,处于挂起状态。NVIC会记录下这个挂起的中断状态。
-
当高优先级的中断执行完毕后,NVIC会回到之前挂起的中断继续执行。这个过程是自动的,由NVIC硬件机制来完成。这种机制使得STM32能够很好地处理嵌套中断,保证中断处理的顺序性和正确性。
- 中断向量表
-
NVIC和中断向量表密切相关。中断向量表是一个存储在特定地址空间(如STM32的Flash存储器的起始地址附近)的表,它存储了中断处理函数的入口地址。
-
当中断发生时,NVIC会根据中断的类型(不同的中断源对应不同的中断类型)从中断向量表中找到对应的中断处理函数入口地址,然后跳转到该地址执行中断服务例程(ISR)。例如,在STM32中,外部中断0的向量地址是固定的,当外部中断0发生时,NVIC就会从向量表中获取该中断的处理函数地址,开始执行中断服务例程。
- NVIC相关寄存器的介绍
STM32 F1系列微控制器的NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)用于管理和调度中断事件,其相关寄存器如下:
使能与禁止相关寄存器
-
ISER(中断使能寄存器组):用于使能中断。STM32F1系列有3个ISER寄存器(ISER[0]、ISER[1]、ISER[2]),每个位对应一个中断,写1使能相应中断,写0无效。
-
ICER(中断除能寄存器组)**:用于禁止中断。与ISER作用相反,写1禁止相应中断,写0无效。
中断挂起相关寄存器
ISPR(中断挂起控制寄存器组)**:用于将正在进行的中断挂起,以便执行同级或更高级别的中断。写1挂起相应中断,写0无效。
ICPR(中断解挂控制寄存器组)**:用于将挂起的中断解挂。写1解挂相应中断,写0无效。
中断状态相关寄存器
-IABR(中断激活标志位寄存器组)**:只读寄存器,用于指示中断是否处于激活状态。每一位对应一个中断,若某位为1,表示相应中断正在执行。
中断优先级相关寄存器
IPR(中断优先级控制寄存器组)**:用于设置中断优先级。STM32F1系列使用8位中的高4位([7:4])来设置中断优先级,低4位保留。优先级数值越小,优先级越高。
- **SCB_AIRCR(应用中断和复位控制寄存器)**:用于设置NVIC的优先级分组策略。PRIGROUP[10:8]位决定中断的抢占优先级与响应优先级的组合方式。
软件触发中断寄存器
STIR(软件触发中断寄存器组)**:向该寄存器写入中断号(低9位)可触发相应中断。
这些寄存器共同协作,实现了STM32 F1系列微控制器对中断的高效管理。
- NVIC的工作原理
STM32 F1系列的NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)工作原理如下:
- 中断请求检测
当外设或系统事件触发中断请求时,NVIC会检测到该请求。如果该中断已被使能(通过ISER寄存器),NVIC将根据中断优先级决定是否响应。
- 中断优先级判断
NVIC根据中断的优先级来决定处理顺序。STM32的中断优先级分为抢占优先级和响应优先级:
-
**抢占优先级**:数值越小,优先级越高。高抢占优先级的中断可以打断低抢占优先级的中断。
-
**响应优先级**:当抢占优先级相同时,响应优先级起作用,数值越小,优先级越高。
-
**自然优先级**:由硬件固定,当抢占优先级和响应优先级都相同时,自然优先级决定中断的处理顺序。
- 中断响应与处理
-
**中断响应**:如果中断的优先级高于当前执行的中断或任务,NVIC会暂停当前执行,保存现场,然后跳转到对应的中断处理函数。
-
**中断处理**:执行中断服务例程(ISR),处理中断事件。
-
**中断返回**:中断处理完成后,恢复现场,返回到被中断的程序继续执行。
- 中断嵌套
NVIC支持中断嵌套,即在处理一个中断时,可以被更高优先级的中断打断。高抢占优先级的中断可以打断低抢占优先级的中断,但高响应优先级的中断不能打断低响应优先级的中断(当它们具有相同的抢占优先级时)。
- 中断优先级配置
通过NVIC的IPR寄存器和SCB_AIRCR寄存器配置中断优先级和优先级分组:
-
**优先级分组**:通过`NVIC_PriorityGroupConfig()`函数设置,决定抢占优先级和响应优先级的位数分配。
-
**优先级设置**:通过`NVIC_SetPriority()`函数设置具体中断的优先级。
- 中断使能与禁止
-
**使能中断**:通过ISER寄存器使能特定中断。
-
**禁止中断**:通过ICER寄存器禁止特定中断。
7. 中断挂起与解挂
-
**中断挂起**:通过ISPR寄存器挂起正在执行的中断。
-
**中断解挂**:通过ICPR寄存器解挂中断。
- 中断向量表
中断向量表存储了中断处理函数的入口地址。当中断发生时,NVIC根据中断号从向量表中获取对应的处理函数地址并跳转执行。STM32的中断向量表位于内部Flash存储器的起始地址。
通过以上机制,STM32 F1系列的NVIC能够高效地管理和调度多个中断请求,确保系统能够快速响应和处理各种异步事件。
- NVIC中断优先级分组
CM3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。
STM32并没有使用CM3内核的全部东西,而是只用了它的一部分。
STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级。
STM32F103系列上面,又只有60个可屏蔽中断(在107系列才有68个)
几十个中断,怎么管理?
中断管理方法:
首先,对STM32中断进行分组,组0~4。同时,对每个中断设置一个抢占优先级和一个响应优先级值。
分组配置是在寄存器SCB->AIRCR中配置:

抢占优先级 & 响应优先级区别:
高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。
抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。
抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。
如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;


中断优先级分组函数:
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
分组设置好之后,怎么设置单个中断的抢占优先级和响应优先级?
中断设置相关寄存器
__IO uint8_t IP[240]; //中断优先级控制的寄存器组
__IO uint32_t ISER[8]; //中断使能寄存器组
__IO uint32_t ICER[8]; //中断失能寄存器组
__IO uint32_t ISPR[8]; //中断挂起寄存器组
__IO uint32_t ICPR[8]; //中断解挂寄存器组
__IO uint32_t IABR[8]; //中断激活标志位寄存器组

对于每个中断怎么设置优先级?
中断优先级控制的寄存器组:IP[240]
全称是:Interrupt Priority Registers
240个8位寄存器,每个中断使用一个寄存器来确定优先级。STM32F10x系列一共60个可屏蔽中断,使用IP[59]~IP[0]。
每个IP寄存器的高4位用来设置抢占和响应优先级(根据分组),低4位没有用到。

中断使能寄存器组:ISER[8]
作用:用来使能中断
32位寄存器,每个位控制一个中断的使能。STM32F10x只有60个可屏蔽中断,所以只使用了其中的ISER[0]和ISER[1]。
ISER[0]的bit0~bit31分别对应中断0~31。ISER[1]的bit0~27对应中断32~59;
void NVIC_Init ( NVIC_InitTypeDef * NVIC_InitStruct ) ;
中断失能寄存器组:ICER[8]
作用:用来失能中断
32位寄存器,每个位控制一个中断的失能。STM32F10x只有60个可屏蔽中断,所以只使用了其中的ICER[0]和ICER[1]。
ICER[0]的bit0~bit31分别对应中断0~31。ICER[1]的bit0~27对应中断32~59;
配置方法跟ISER一样。
void NVIC_Init ( NVIC_InitTypeDef * NVIC_InitStruct );
中断挂起控制寄存器组:ISPR[8]
作用:用来挂起中断
中断解挂控制寄存器组:ICPR[8]
作用:用来解挂中断
static __INLINE void NVIC_SetPendingIRQ ( IRQn_Type IRQn ) ;
static __INLINE uint32_t NVIC_GetPendingIRQ ( IRQn_Type IRQn ) ;
static __INLINE void NVIC_ClearPendingIRQ ( IRQn_Type IRQn );
u中断激活标志位寄存器组:IABR [8]
作用:只读,通过它可以知道当前在执行的中断是哪一个
如果对应位为1,说明该中断正在执行。
static __INLINE uint32_t NVIC_GetActive ( IRQn_Type IRQn )

