STM32-M0中断优先级介绍

  先解释中断优先级,后面讲代码的实现。

  差异:M0的中断优先级相比于M4,没有用到分组,且只用到了2个bit位(即0~3)来设置,数值越小,优先级越高;同等优先级,根据终端号的大小来决定谁先执行。

  根据下面这张编程手册里的图来说明:

 

  从上往下看,共32个IRQ中断,每个中断优先级占8个位,一个寄存器存4个中断的优先级,所以M0的IRQ中断最多只有32个;表27中高亮部分,说的是只用高两位来表示优先级的值,低六位填0,没有用到。

  还有一个要提到的是word-accessible,就是寄存器只能按字操作。

  M0的中断优先级就讲完了,还是很简单的,那我们讲一下代码的实现:

 

 1 void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
 2 {
 3   uint32_t tmppriority = 0x00;
 4   
 5   /* Check the parameters */
 6   assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
 7   assert_param(IS_NVIC_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPriority));  
 8     
 9   if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
10   {
11     /* Compute the Corresponding IRQ Priority --------------------------------*/    
12     tmppriority = NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel >> 0x02];
13     tmppriority &= (uint32_t)(~(((uint32_t)0xFF) << ((NVIC_InitStruct->NVIC_IRQChannel & 0x03) * 8)));
14     tmppriority |= (uint32_t)((((uint32_t)NVIC_InitStruct->NVIC_IRQChannelPriority << 6) & 0xFF) << ((NVIC_InitStruct->NVIC_IRQChannel & 0x03) * 8));    
15     
16     NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel >> 0x02] = tmppriority;
17     
18     /* Enable the Selected IRQ Channels --------------------------------------*/
19     NVIC->ISER[0] = (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
20   }
21   else
22   {
23     /* Disable the Selected IRQ Channels -------------------------------------*/
24     NVIC->ICER[0] = (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
25   }
26 }

  这段代码是官方库的代码,我说下思路:

    1、要设置优先级,要先找到该中断的优先级寄存器在哪个寄存器里,将中断号除以4,得到对应寄存器,读该寄存器的值给变量tmppriority ,代码如下:

      tmppriority = NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel >> 0x02];

    2、再判断该终端号的优先级值在对应寄存器的哪个位置,并清零该8位,共四个位置为:0~7、8~15、16~23、24~31,代码如下,NVIC_InitStruct->NVIC_IRQChannel & 0x03表示对4求余的结果;

      tmppriority &= (uint32_t)(~(((uint32_t)0xFF) << ((NVIC_InitStruct->NVIC_IRQChannel & 0x03) * 8)));

    3、接着给该8位写入要设置的优先级的值,由于优先级只占了8位的高两位,所以NVIC_InitStruct->NVIC_IRQChannelPriority << 6写高两位,再左移到在该寄存器中对应的位置,和读到寄存器的值tmppriority 与运算,就完成了对该寄存器的对应位写优先级值得操作,记住,这是一个32位的数;

      tmppriority |= (uint32_t)((((uint32_t)NVIC_InitStruct->NVIC_IRQChannelPriority << 6) & 0xFF) << ((NVIC_InitStruct->NVIC_IRQChannel & 0x03) * 8)); 

    4、把这个32位的数写入该寄存器中;  

      NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel >> 0x02] = tmppriority;

    废话:((NVIC_InitStruct->NVIC_IRQChannel & 0x03) * 8))这个语句是用来获得在寄存器中的偏移值得,用这个偏移值就能把8位数进行左移。

完!

原文地址:https://www.cnblogs.com/leo0621/p/8694752.html