1 中斷分組
嵌套中斷的含義: 高優先級中斷能打斷低優先級中斷

翻譯:
- STM32分組為:組0-4(沒組都有16個優先級)
- 分組配置在寄存器SCB->AIRCR中
使用示例:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//設定NVIC中斷分組2:2位搶占優先級,2位響應優先級
#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority
#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000)
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
/* Check the parameters */
assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
/* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
如下圖這個圖中用了8位:
SCB->AIRCR 寄存器和IP寄存器
首先兩者聯系,SCB->AIRCR 寄存器的10:8位bit,決定了,IP寄存器4:7bit的高四位的搶占與響應位的配置設定:
那麼SCB->AIRCR 寄存器的10:8位bit怎麼決定這個配置設定呢?
AIRCR 寄存器的10:8位,設定幾位搶占,幾位響應。舉例如下:
AIRCR寄存器8:10與IP寄存器4:7
AIRCR寄存器8:10 IP寄存器4:7
0 111 搶占:0bit,響應:4bit
1 110 搶占:1bit,響應:3bit
2 101 搶占:2bit,響應:2bit
3 100 搶占:3bit,響應:1bit
4 011 搶占:4bit,響應:0bit
怎麼了解這個表呢?
AIRCR寄存器8:10是111,表示7,即ip寄存器的第四位到第七位為止是響應級(從0開始),本來就ip寄存器的4:7bit,那4,5,6,7bit,都表示響應
AIRCR寄存器8:10是100,表示4,ip寄存器的第四位到第四位表示響應級。即一位表示響應級
設定響應的例子:
MY_NVIC_Init(3,2,EXTI2_IRQn,2); //搶占3,子優先級2,組2
2 中斷程式設計
中斷程式設計的三步曲:
第一步:使能外設某個中斷,具體由對應的中斷使能位控制。(例如:我們使用到GPIO之前必須開啟GPIO端口的時鐘,用到EXTI必須開啟AFIO時鐘)
第二步:初始化NVIC_InitTypeDef結構體,配置中斷優先級分組,設定搶占優先級和響應優先級,使能中斷請求
第三步:編寫中斷服務函數,在stm32f0xx_it.c檔案中,都有一個根據中斷向量表,實作的一個空的中斷服務函數,需要我們自己重新編寫
3 中斷應用
NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn; //中斷号
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //搶占優先級
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //次優先級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
uint8_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
{
/* Compute the Corresponding IRQ Priority --------------------------------*/
tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
tmppre = (0x4 - tmppriority);
tmpsub = tmpsub >> tmppriority;
tmppriority = NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
tmppriority |= (uint8_t)(NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub);
tmppriority = tmppriority << 0x04;
NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;// IP寄存器設定中斷優先級
/* Enable the Selected IRQ Channels --------------------------------------*/
NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
else
{
/* Disable the Selected IRQ Channels -------------------------------------*/
NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
nvic中斷寄存器的配置分布:
typedef struct
{
__IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
uint32_t RESERVED5[644];
__O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
} NVIC_Type;