CM3内核支撑256个中止,其间包含了16个内核中止和240个外部中止,而且具有256级的可编程中止设置。但STM32并没有运用CM3内核的悉数东西,而是只用了它的一部分。STM32有84个中止,包含16个内核中止和68个可屏蔽中止,具有16级可编程的中止优先级。而咱们常用的便是这68个可屏蔽中止,可是STM32的68个可屏蔽中止,在STM32F103系列上面,又只要60个(在107系列才有68个)。
在MDK内,与NVIC相关的寄存器,MDK为其界说了如下的结构体:
STM32的中止在这些寄存器的操控下有序的履行的。只要了解这些中止寄存器,才干了解STM32的中止。下面扼要介绍这几个寄存器:
ISER[2]:ISER全称是:InterruptSet-EnableRegisters,这是一个中止使能寄存器组。上面说了STM32F103的可屏蔽中止只要60个,这儿用了2个32位的寄存器,一共能够表明64个中止。而STM32F103只用了其间的前60位。ISER[0]的bit0~bit31别离对应中止0~31。ISER[1]的bit0~27对应中止32~59;这样一共60个中止就别离对应上了。你要使能某个中止,有必要设置相应的ISER位为1,使该中止被使能(这儿仅仅是使能,还要合作中止分组、屏蔽、IO口映射等设置才算是一个完好的中止设置)。详细每一位对应哪个中止,请参阅stm32f10x_nvic..h里边的第36行处。
ICER[2]:全称是:InterruptClear-EnableRegisters,是一个中止除能寄存器组。该寄存器组与ISER的效果恰好相反,是用来铲除某个中止的使能的。其对应位的功用,也和ICER相同。这儿要专门设置一个ICER来铲除中止位,而不是向ISER写0来铲除,是由于NVIC的这些寄存器都是写1有用的,写0是无效的。
ISPR[2]:全称是:InterruptSet-PendingRegisters,是一个中止挂起操控寄存器组。每个位对应的中止和ISER是相同的。经过置1,能够将正在进行的中止挂起,而履行同级或更高等级的中止。写0是无效的。
ICPR[2]:全称是:InterruptClear-PendingRegisters,是一个中止解挂操控寄存器组。其效果与ISPR相反,对应位也和ISER是相同的。经过设置1,能够将挂起的中止接挂。写0无效。
IABR[2]:全称是:InterruptActiveBitRegisters,是一个中止激活标志位寄存器组。这是一个只读寄存器,经过它能够知道当时在履行的中止是哪一个。在中止履行完了由硬件主动清零。对应位所代表的中止和ISER相同,假如为1,则表明该位所对应的中止正在被履行。
IPR[15]:全称是:InterruptPriorityRegisters,是一个中止优先级操控的寄存器组。这个寄存器组适当重要!STM32的中止分组与这个寄存器组密切相关。由于STM32的中止多达60多个,所以STM32选用中止分组的办法来确认中止的优先级。IPR寄存器组由15个32bit的寄存器组成,每个可屏蔽中止占用8bit,这样一共能够表明15*4=60个可屏蔽中止。刚好和STM32的可屏蔽中止数持平。IPR[0]的[31~24],[23~16],[15~8],[7~0]别离对应中止3~0,顺次类推,一共对应60个外部中止。而每个可屏蔽中止占用的8bit并没有悉数运用,而是只用了高4位。这4位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。而这两个优先级各占几个位又要依据SCB->AIRCR中的中止断分组设置来决议。
这儿简略介绍一下STM32的中止分组:STM32将中止分为5个组,组0~4。该分组的设置是由SCB->AIRCR寄存器的bit10~8来界说的。详细的分配联系如表
经过这个表,咱们就能够清楚的看到组0~4对应的装备联系,例如组设置为3,那么此刻一切的60个中止,每个中止的中止优先寄存器的高四位中的最高3位是抢占优先级,低1位是呼应优先级。每个中止,你能够设置抢占优先级为0~7,呼应优先级为1或0。抢占优先级的等级高于呼应优先级。而数值越小所代表的优先级就越高。
这儿需求留意两点:榜首,假如两个中止的抢占优先级和呼应优先级都是相同的话,则看哪个中止先发生就先履行;第二,高优先级的抢占优先级是能够打断正在进行的低抢占优先级中止的。而抢占优先级相同的中止,高优先级的呼应优先级不能够打断低呼应优先级的中止。
运用库函数完成以上中止分组设置以及中止优先级办理,使得咱们今后的中止设置简略化。NVIC中止办理函数主要在misc.c文件里边。
首先是中止优先级分组函数NVIC_PriorityGroupConfig,这个函数的效果是对中止的优先级进行分组,这个函数在体系中只能被调用一次,一旦分组确认就最好不要更改。
比方咱们设置整个体系的中止优先级分组值为2(2位抢占优先级,2位呼应优先级”),那么办法是:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
设置好了体系中止分组,那么关于每个中止又怎样确认他的抢占优先级和呼应优先级呢?下面看一个重要的函数为中止初始化函数NVIC_Init,其函数申明为:
voidNVIC_Init(NVIC_InitTypeDef*NVIC_InitStruct)
其间NVIC_InitTypeDef是一个结构体,能够看看结构体的成员变量:
比方咱们要使能串口1的中止,一起设置抢占优先级为1,子优先级位2,初始化的办法是:
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//串口 1 中止
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;// 抢占优先级为 1
- NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;// 子优先级位 2
- NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//IRQ 通道使能
- NVIC_Init(&NV%&&&&&%_InitStructure);