天天看点

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;