天天看點

stm32f407 中斷問題1 中斷分組2 中斷程式設計

1 中斷分組

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

stm32f407 中斷問題1 中斷分組2 中斷程式設計

翻譯:

stm32f407 中斷問題1 中斷分組2 中斷程式設計
  1. STM32分組為:組0-4(沒組都有16個優先級)
  2. 分組配置在寄存器SCB->AIRCR中
stm32f407 中斷問題1 中斷分組2 中斷程式設計

使用示例:

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;
}
           
stm32f407 中斷問題1 中斷分組2 中斷程式設計

如下圖這個圖中用了8位:

stm32f407 中斷問題1 中斷分組2 中斷程式設計

SCB->AIRCR 寄存器和IP寄存器

首先兩者聯系,SCB->AIRCR 寄存器的10:8位bit,決定了,IP寄存器4:7bit的高四位的搶占與響應位的配置設定:

stm32f407 中斷問題1 中斷分組2 中斷程式設計
stm32f407 中斷問題1 中斷分組2 中斷程式設計
stm32f407 中斷問題1 中斷分組2 中斷程式設計

那麼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;