STM32 NVIC 中斷優(yōu)先級管理
在MDK內(nèi),與NVIC相關(guān)的寄存器,MDK為其定義了如下的結(jié)構(gòu)體:
本文引用地址:http://m.butianyuan.cn/article/201611/317044.htm- typedefstruct
- {
- 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的中斷在這些寄存器的控制下有序的執(zhí)行的。只有了解這些中斷寄存器,才能了解STM32的中斷。下面簡要介紹這幾個寄存器:
ISER[2]:ISER全稱是:InterruptSet-EnableRegisters,這是一個中斷使能寄存器組。上面說了STM32F103的可屏蔽中斷只有60個,這里用了2個32位的寄存器,總共可以表示64個中斷。而STM32F103只用了其中的前60位。ISER[0]的bit0~bit31分別對應(yīng)中斷0~31。ISER[1]的bit0~27對應(yīng)中斷32~59;這樣總共60個中斷就分別對應(yīng)上了。你要使能某個中斷,必須設(shè)置相應(yīng)的ISER位為1,使該中斷被使能(這里僅僅是使能,還要配合中斷分組、屏蔽、IO口映射等設(shè)置才算是一個完整的中斷設(shè)置)。具體每一位對應(yīng)哪個中斷,請參考stm32f10x_nvic..h里面的第36行處。
ICER[2]:全稱是:InterruptClear-EnableRegisters,是一個中斷除能寄存器組。該寄存器組與ISER的作用恰好相反,是用來清除某個中斷的使能的。其對應(yīng)位的功能,也和ICER一樣。這里要專門設(shè)置一個ICER來清除中斷位,而不是向ISER寫0來清除,是因為NVIC的這些寄存器都是寫1有效的,寫0是無效的。
ISPR[2]:全稱是:InterruptSet-PendingRegisters,是一個中斷掛起控制寄存器組。每個位對應(yīng)的中斷和ISER是一樣的。通過置1,可以將正在進行的中斷掛起,而執(zhí)行同級或更高級別的中斷。寫0是無效的。
ICPR[2]:全稱是:InterruptClear-PendingRegisters,是一個中斷解掛控制寄存器組。其作用與ISPR相反,對應(yīng)位也和ISER是一樣的。通過設(shè)置1,可以將掛起的中斷接掛。寫0無效。
IABR[2]:全稱是:InterruptActiveBitRegisters,是一個中斷激活標志位寄存器組。這是一個只讀寄存器,通過它可以知道當前在執(zhí)行的中斷是哪一個。在中斷執(zhí)行完了由硬件自動清零。對應(yīng)位所代表的中斷和ISER一樣,如果為1,則表示該位所對應(yīng)的中斷正在被執(zhí)行。
IPR[15]:全稱是:InterruptPriorityRegisters,是一個中斷優(yōu)先級控制的寄存器組。這個寄存器組相當重要!STM32的中斷分組與這個寄存器組密切相關(guān)。因為STM32的中斷多達60多個,所以STM32采用中斷分組的辦法來確定中斷的優(yōu)先級。IPR寄存器組由15個32bit的寄存器組成,每個可屏蔽中斷占用8bit,這樣總共可以表示15*4=60個可屏蔽中斷。剛好和STM32的可屏蔽中斷數(shù)相等。IPR[0]的[31~24],[23~16],[15~8],[7~0]分別對應(yīng)中斷3~0,依次類推,總共對應(yīng)60個外部中斷。而每個可屏蔽中斷占用的8bit并沒有全部使用,而是只用了高4位。這4位,又分為搶占優(yōu)先級和子優(yōu)先級。搶占優(yōu)先級在前,子優(yōu)先級在后。而這兩個優(yōu)先級各占幾個位又要根據(jù)SCB->AIRCR中的中斷斷分組設(shè)置來決定。
這里簡單介紹一下STM32的中斷分組:STM32將中斷分為5個組,組0~4。該分組的設(shè)置是由SCB->AIRCR寄存器的bit10~8來定義的。具體的分配關(guān)系如表
通過這個表,我們就可以清楚的看到組0~4對應(yīng)的配置關(guān)系,例如組設(shè)置為3,那么此時所有的60個中斷,每個中斷的中斷優(yōu)先寄存器的高四位中的最高3位是搶占優(yōu)先級,低1位是響應(yīng)優(yōu)先級。每個中斷,你可以設(shè)置搶占優(yōu)先級為0~7,響應(yīng)優(yōu)先級為1或0。搶占優(yōu)先級的級別高于響應(yīng)優(yōu)先級。而數(shù)值越小所代表的優(yōu)先級就越高。
這里需要注意兩點:第一,如果兩個中斷的搶占優(yōu)先級和響應(yīng)優(yōu)先級都是一樣的話,則看哪個中斷先發(fā)生就先執(zhí)行;第二,高優(yōu)先級的搶占優(yōu)先級是可以打斷正在進行的低搶占優(yōu)先級中斷的。而搶占優(yōu)先級相同的中斷,高優(yōu)先級的響應(yīng)優(yōu)先級不可以打斷低響應(yīng)優(yōu)先級的中斷。
使用庫函數(shù)實現(xiàn)以上中斷分組設(shè)置以及中斷優(yōu)先級管理,使得我們以后的中斷設(shè)置簡單化。NVIC中斷管理函數(shù)主要在misc.c文件里面。
首先是中斷優(yōu)先級分組函數(shù)NVIC_PriorityGroupConfig,這個函數(shù)的作用是對中斷的優(yōu)先級進行分組,這個函數(shù)在系統(tǒng)中只能被調(diào)用一次,一旦分組確定就最好不要更改。
比如我們設(shè)置整個系統(tǒng)的中斷優(yōu)先級分組值為2(2位搶占優(yōu)先級,2位響應(yīng)優(yōu)先級”),那么方法是:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
設(shè)置好了系統(tǒng)中斷分組,那么對于每個中斷又怎么確定他的搶占優(yōu)先級和響應(yīng)優(yōu)先級呢?下面看一個重要的函數(shù)為中斷初始化函數(shù)NVIC_Init,其函數(shù)申明為:
voidNVIC_Init(NVIC_InitTypeDef*NVIC_InitStruct)
其中NVIC_InitTypeDef是一個結(jié)構(gòu)體,可以看看結(jié)構(gòu)體的成員變量:
- typedefstruct
- {
- uint8_t NVIC_IRQChannel;//定義初始化的是哪個中斷,這個我們可以在 stm32f10x.h 中找到每個中斷對應(yīng)的名字。例如 USART1_IRQn。
- uint8_t NVIC_IRQChannelPreemptionPriority;//定義這個中斷的搶占優(yōu)先級別。
- uint8_t NVIC_IRQChannelSubPriority;//定義這個中斷的子優(yōu)先級別。
- FunctionalState NVIC_IRQChannelCmd;//該中斷是否使能。
- }NVIC_InitTypeDef;
比如我們要使能串口1的中斷,同時設(shè)置搶占優(yōu)先級為1,子優(yōu)先級位2,初始化的方法是:
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//串口 1 中斷
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;// 搶占優(yōu)先級為 1
- NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;// 子優(yōu)先級位 2
- NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//IRQ 通道使能
- NVIC_Init(&NVIC_InitStructure);
評論