步骤一  设置中断分组

STM32中断规则

中断优先级分为抢占式优先级和子优先级。对于每一个中断需事先设置其抢占式优先级和子优先级。 

抢占式优先级级别高的中断可以打断抢占式优先级级别地的中断。抢占式优先级级别相同时,互相均不能打断对方中断执行,且同时产生两个中断时,按照中断的子优先级顺序执行中断。

例子:中断2设置抢占式优先级为1,子优先级为2。中断3的抢占式优先级为2,子优先级为1。中断8的抢占式优先级为1,子优先级为3

此时中断优先级:中断2>中断8>中断3

具体的 当中断3执行过程中,中断2或中断8任意一个产生,均可以使中断3挂起而先执行后产生的中断。另外当中断2和中断8同时产生的时候,优先执行中断2中断2执行完毕后执行中断8。

中断分组的实现

COM3内核中存在设置中断优先级分组的寄存器(IP[240]:)

IP寄存器有240个8Bbit的寄存器。STM32只是使用60个。每个寄存器都可以设置特定的一个中断的抢占式优先级和子优先级的级别。比如中断2,其对应的IP寄存器的值可能为      01 10  0000(这是中断优先级分组设置为2的情况下 即两位用来标识抢占式优先级 两位用来标识子优先级) 或 1 010  0000。STM32只是使用其高四位,另外两种可能的设置方法取决于中断分组设置。中断分组的设置由SCB->IRCR寄存器(bit10~8)设置决定。

中断分组可分为5组:当SCB->AIRCR寄存器(bit10~8)数分别为111、110、101、011、001时  ,不同类优先级能表示位数比:抢占式优先级:子优先级=  0:4   or    1:3    or   2:2   or   3:1   or   4:0

分组使用的函数

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) //NVIC_PriorityGroup的值为NVIC_PriorityGroup_X ,其中X=0~4,分别代表不同中断分组情况
{
 assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
 SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}

步骤二  中断初始化

对中断初始化结构体相关赋值

中断初始化的结构体

typedef struct
{
 uint8_t NVIC_IRQChannel;                    //要设置的中断号 
 uint8_t NVIC_IRQChannelPreemptionPriority;  //抢占式优先级级别
 uint8_t NVIC_IRQChannelSubPriority;         //子优先级级别
 FunctionalState NVIC_IRQChannelCmd;         //中断使能
} NVIC_InitTypeDef;

中断初始化

中断初始化函数

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)  
{
  uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
  
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
  assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));  
  assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
    
  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 = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
    tmppriority |=  NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
    tmppriority = tmppriority << 0x04;
        
    NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
    
    /* 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);
  }
}

根据STM32中断规则实现多级中断嵌套

参考

《Cortex-M3权威指南》

《STM32F1开发指南-库函数版本》