STM32學習心得十三:NVIC中斷優先級管理

記錄一下,方便以後翻閱~
主要內容:
1) NVIC中斷優先級分組;
2) NVIC中斷優先級設置。
官方資料:《STM32中文參考手冊V10》第9章——中斷和事件
1. NVIC中斷優先級分組
1.1 CM3內核支持256箇中斷,其中包含16個內核中斷和240個外部中斷,並且具有256級的可編程中斷設置;
1.2 STM32並沒有使用CM3內核的全部東西,只用了它的一部分;
1.3 STM32有84箇中斷,包括16個內核中斷和68個可屏蔽中斷,具有16級可編程的中斷優先級;
1.4 STM32F103系列上面,又只有60個可屏蔽中斷(在107系列纔有68個)。
2. NVIC中斷優先級向量表(STM32F10xx產品(非互聯型))
在這裏插入圖片描述
在這裏插入圖片描述
3. NVIC中斷優先級管理方法
3.1 對STM32中斷進行分組,組0~4。同時,對每個中斷設置一個搶佔優先級和一個響應優先級值;
3.2 分組配置是在寄存器SCB->AIRCR中配置:
在這裏插入圖片描述
3.3 分組配置是在寄存器SCB->AIRCR中配置。
4. 搶佔優先級和響應優先級區別
4.1 高優先級(值越小越高)的搶佔優先級是可以打斷正在進行的低搶佔優先級中斷的;
4.2 搶佔優先級相同的中斷,高響應優先級不可以打斷低響應優先級的中斷;
4.3 搶佔優先級相同的中斷,當兩個中斷同時發生的情況下,高響應優先級先執行;
4.4 如果兩個中斷的搶佔優先級和響應優先級都是一樣的話,則看哪個中斷先發生就先執行。
舉例:
假定設置中斷優先級組爲2,
設置中斷3(RTC中斷)的搶佔優先級爲2,響應優先級爲1;
設置中斷6(外部中斷0)的搶佔優先級爲3,響應優先級爲0;
設置中斷7(外部中斷1)的搶佔優先級爲2,響應優先級爲0。
那麼這3箇中斷的優先級順序爲:中斷7>中斷3>中斷6
**備註:**一般情況下,系統代碼執行過程中,只設置一次中斷優先級分組,比如分組2,設置好分組之後一般不會再改變分組。隨意改變分組會導致中斷管理混亂,程序出現意想不到的執行結果。
5. 中斷優先級分組函數:

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);//

6. MDK中NVIC寄存器結構體

typedef struct
{
__IO uint32_t ISER[8];         //中斷使能寄存器組//         
uint32_t RESERVED0[24];                                   
__IO uint32_t ICER[8];         //中斷失能寄存器組//              
uint32_t  RSERVED1[24];                                    
__IO uint32_t ISPR[8];         //中斷掛起寄存器組//           
uint32_t RESERVED2[24];                                   
__IO uint32_t ICPR[8];         //中斷解掛寄存器組//         
uint32_t RESERVED3[24];                                   
__IO uint32_t IABR[8];         //中斷激活標誌位寄存器組//            
uint32_t RESERVED4[56];                                   
__IO uint8_t    IP[240];       //中斷優先級控制的寄存器組//                 
uint32_t RESERVED5[644];                                  
__O  uint32_t STIR;                         
} 
NVIC_Type; 

7. 每個中斷的優先級設置
1.1 中斷優先級控制的寄存器組:IP[240] (全稱:Interrupt Priority Registers)
240個8位寄存器,每個中斷使用一個寄存器來確定優先級。STM32F10x系列一共60個可屏蔽中斷,使用IP[59]~IP[0]。每個IP寄存器的高4位用來設置搶佔和響應優先級(根據分組),低4位沒有用到。
相關函數:

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

7.2 中斷使能寄存器組:ISER[8] (作用:用來使能中斷)
32位寄存器,每個位控制一箇中斷的使能。STM32F10x只有60個可屏蔽中斷,所以只使用了其中的ISER[0]和ISER[1]。ISER[0]的bit0bit31分別對應中斷031。ISER[1]的bit027對應中斷3259。
相關函數:

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

7.3 中斷失能寄存器組:ICER[8] (作用:用來失能中斷)
32位寄存器,每個位控制一箇中斷的失能。STM32F10x只有60個可屏蔽中斷,所以只使用了其中的ICER[0]和ICER[1]。ICER[0]的bit0bit31分別對應中斷031。ICER[1]的bit027對應中斷3259。
相關函數:

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

7.4 中斷掛起控制寄存器組:ISPR[8] (作用:用來掛起中斷)
7.5 中斷解掛控制寄存器組:ICPR[8] (作用:用來解掛中斷)

//7.4和7.5涉及的部分相關函數//
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);
//以上函數位於core_cm3.h文件中//

7.6 中斷激活標誌位寄存器組:IABR [8] (作用:只讀,通過它可以知道當前在執行的中斷是哪一個)
如果對應位爲1,說明該中斷正在執行。
相關函數:

static __INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn);

8. 中斷參數初始化函數解讀

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
typedef struct
{
uint8_t NVIC_IRQChannel;                             //設置中斷通道//
uint8_t NVIC_IRQChannelPreemptionPriority;           //設置搶佔優先級//
uint8_t NVIC_IRQChannelSubPriority;                  //設置相應優先級//
FunctionalState NVIC_IRQChannelCmd;                  //使能//
}NVIC_InitTypeDef;                                   //位於misc.h文件中//
NVIC_InitTypeDef   NVIC_InitStructure; 
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;          //串口1中斷,中斷類型參考stm32f10x.h中的IRQn_Tpye;//
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;    //搶佔優先級爲1//
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 2;          //響應優先級位2//
NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE;             //IRQ通道使能//
NVIC_Init(&NVIC_InitStructure);                            //根據上面指定的參數初始化NVIC寄存器//

9. 中斷優先級設置步驟
9.1 系統運行後先設置中斷優先級分組;

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);  //整個系統執行過程中,只設置一次中斷分組;//

9.2 針對每個中斷,設置對應的搶佔優先級和響應優先級;

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

9.3 如果需要掛起/解掛,查看中斷當前激活狀態,分別調用相關函數即可。
舊知識點:
1)複習基於庫函數的初始化函數的一般格式,可參考STM32學習心得三:GPIO實驗-基於庫函數
2)複習寄存器地址,可參考STM32學習心得四:GPIO實驗-基於寄存器STM32學習心得五:GPIO實驗-基於位操作
3)複習寄存器地址名稱映射,可參考STM32學習心得六:相關C語言學習及寄存器地址名稱映射解讀

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章