CM3 内核支撑256 个中止,其间包含了16 个内核中止和240 个外部中止,而且具有256
级的可编程中止设置。但STM32 并没有运用CM3 内核的悉数东西,而是只用了它的一部分。
STM32 有76 个中止,包含16 个内核中止和60 个可屏蔽中止,具有16 级可编程的中止优先级。
而咱们常用的便是这60 个可屏蔽中止,所以咱们就只针对这60 个可屏蔽中止进行介绍。
在 MDK 内,与NVIC相关的寄存器,MDK 为其界说了如下的结构体:
typedef struct
{
vu32 ISER[2];
u32 RESERVED0[30];
vu32 ICER[2];
u32 RSERVED1[30];
vu32 ISPR[2];
u32 RESERVED2[30];
vu32 ICPR[2];
u32 RESERVED3[30];
vu32 IABR[2];
u32 RESERVED4[62];
vu32 IPR[15];
} NVIC_TypeDef;
STM32 的中止在这些寄存器的操控下有序的履行的。了解这些中止寄存器,你才干便利的
运用STM32 的中止。下面要点介绍这几个寄存器:
ISER[2]:ISER 全称是:Interrupt Set-Enable Registers,这是一个中止使能寄存器组。上面
说了STM32 的可屏蔽中止只需60 个,这儿用了2 个32 位的寄存器,一共能够表明64 个中止。
而STM32 只用了其间的前60 位。ISER[0]的bit0~bit31 别离对应中止0~31。ISER[1]的bit0~27
对应中止32~59;这样一共60 个中止就别离对应上了。你要使能某个中止,有必要设置相应的ISER
位为1,使该中止被使能(这儿仅仅是使能,还要合作中止分组、屏蔽、IO 口映射等设置才算是
一个完好的中止设置)。详细每一位对应哪个中止,请参阅stm32f10x_nvic..h 里边的第36 行处。
ICER[2]:全称是:Interrupt Clear-Enable Registers,是一个中止除能寄存器组。该寄存器组
与ISER 的效果恰好相反,是用来铲除某个中止的使能的。其对应位的功用,也和ICER 相同。
这儿要专门设置一个ICER 来铲除中止位,而不是向ISER 写0 来铲除,是由于NVIC 的这些寄
存器都是写1 有用的,写0 是无效的。详细为什么这么规划,请看《CM3 威望攻略》第125 页,
NVIC 概览一章。
ISPR[2]:全称是:Interrupt Set-Pending Registers,是一个中止挂起操控寄存器组。每个位
对应的中止和ISER 是相同的。经过置1,能够将正在进行的中止挂起,而履行同级或更高等级
的中止。写0 是无效的。
ICPR[2]:全称是:Interrupt Clear-Pending Registers,是一个中止解挂操控寄存器组。其作
用与ISPR 相反,对应位也和ISER 是相同的。经过设置1,能够将挂起的中止接挂。写0 无效。
IABR[2]:全称是:Active Bit Registers,是一个中止激活标志位寄存器组。对应位所代表
的中止和ISER 相同,假如为1,则表明该位所对应的中止正在被履行。这是一个只读寄存器,
经过它能够知道当时在履行的中止是哪一个。在中止履行完了由硬件主动清零。
IPR[15]:全称是:Interrupt Priority Registers,是一个中止优先级操控的寄存器组。这个寄
存器组适当重要!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 来界说的。详细的分配联系如下表所示:
一切的60 个中止,每个中止的中止优先寄存器的高四位中的最高3 位是抢占优先级,低1 位是
呼应优先级。每个中止,你能够设置抢占优先级为0~7,呼应优先级为1 或0。抢占优先级的
等级高于呼应优先级。而数值越小所代表的优先级就越高。
结合实例阐明一下:假定设置中止优先级组为2,然后设置中止3(RTC 中止)的抢占优先级
为3,呼应优先级为1。中止6(外部中止0)的抢占优先级为4,呼应优先级为0。中止7(外
部中止1)的抢占优先级为3,呼应优先级为0。那么这3 个中止的优先级次序为:中止7>中
断3>中止6。
这儿需求留意 2 点:
假如两个中止的呼应优先级和呼应优先级都是相同的话,则看哪个中止先产生就先履行。
高优先级的抢占优先级是能够打断正在进行的低抢占优先级中止的。而抢占优先级相同的
中止,高优先级的呼应优先级不能够打断低呼应优先级的中止。上面比如中的中止3 和中止7
都能够打断中止6 的中止。而中止7 和中止3 却不能够彼此打断!
经过以上介绍,咱们了解了 STM32 中止设置的大致进程。接下来咱们介绍怎么运用函数
完成以上中止设置,使得咱们今后的中止设置简略化。
第一个介绍的是NVIC 的分组函数MY_NVIC_PriorityGroupConfig,该函数的参数
NVIC_Group 为要设置的分组号,可选规模为0~4,一共5 组。假如参数不合法,将或许导致不
//设置NVIC 分组
//NVIC_Group:NVIC 分组 0~4 一共5 组
void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)
{
u32 temp,temp1;
temp1=(~NVIC_Group)&0x07;//取后三位
temp=SCB->AIRCR; //读取从前的设置
temp&=0X0000F8FF; //清空从前分组
temp|=0X05FA0000; //写入钥匙
temp|=temp1;
SCB->AIRCR=temp; //设置分组
}
经过前面的介绍,咱们知道STM32 的5 个分组是经过设置SCB->AIRCR 的BIT[10:8]来实
现的,而经过2.7.2.1 的介绍咱们知道SCB->AIRCR 的修正需求经过在高16 位写入0X05FA 这
个密钥才干修正的,故在设置AIRCR 之前,应该把密钥加入到要写入的内容的高16 位,以保
证能正常的写入AIRCR。在修正AIRCR 的时分,咱们一般选用读->改->写的过程,来完成不
改动AIRCR 本来的其他设置。以上便是MY_NVIC_PriorityGroupConfig 函数设置中止优先级分
组的思路。
第 二 个 函 数 是NVIC 设置函数MY_NVIC_Init , 该函数有4 个参数, 别离为:
NVIC_PreemptionPriority 、NVIC_SubPriority 、NVIC_Channel 、NVIC_Group 。第一个参数
NVIC_PreemptionPriority 为中止抢占优先级数值,第二个参数NVIC_SubPriority 为中止子优先
级数值,前两个参数的值有必要在规则规模内,不然也或许产生意想不到的过错。第三个参数
NVIC_Channel 为中止的编号(规模为0~59),最终一个参数NVIC_Group 为中止分组设置(范
围为0~4)。该函数代码如下:
//设置NVIC
//NVIC_PreemptionPriority:抢占优先级
//NVIC_SubPriority :呼应优先级
//NVIC_Channel :中止编号
//NVIC_Group :中止分组 0~4
//留意优先级不能超过设定的组的规模!不然会有意想不到的过错
//组区分:
//组0:0 位抢占优先级,4 位呼应优先级
//组1:1 位抢占优先级,3 位呼应优先级
//组2:2 位抢占优先级,2 位呼应优先级
//组3:3 位抢占优先级,1 位呼应优先级
//组4:4 位抢占优先级,0 位呼应优先级
//NVIC_SubPriority 和NVIC_PreemptionPriority 的原则是,数值越小,越优先
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,
u8 NVIC_Group)
{
u32 temp;
u8 IPRADDR=NVIC_Channel/4; //每组只能存4 个,得到组地址
u8 IPROFFSET=NVIC_Channel%4;//在组内的偏移
IPROFFSET=IPROFFSET*8+4; //得到偏移的切当方位
MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组
temp=NVIC_PreemptionPriority<<(4-NVIC_Group);
temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
temp&=0xf;//取低四位
相反操作就OK)
else NVIC->ISER[1]|=1<<(NVIC_Channel-32);
NVIC->IPR[IPRADDR]|=temp<
经过前面的介绍,咱们知道每个可屏蔽中止的优先级的设置是在IPR 寄存器组里边的,每
个中止占8 位,但只用了其间的4 个位,以上代码便是依据中止分组状况,来设置每个中止对
应的高4 位的数值的。当然在该函数里边还引用了MY_NV%&&&&&%_PriorityGroupConfig 这个函数来
设置分组。其实这个分组函数在每个体系里边只需设置一次就够了,设置屡次,则是以最终的
那一次为准。可是只需屡次设置的组号都是相同,就没事。不然前面设置的中止会由于后边组
的改动优先级会产生改动,这点在运用的时分要特别留意!一个体系代码里边,一切的中止分
组都要一致!!,以上代码对要装备的中止号默许是敞开中止的。也便是ISER 中的值设置为1
了。