STM32-NVIC中断嵌套优先级管理器

NVIC简介

NVIC(Nested Vectored Interrupt Controller),中断嵌套向量控制器,是 Cortex‐M3 不可分离的一部分,它与 CM3 内核共同完成对中断的响应。在了解NVIC之前最好简单了解一下CM3内核的中断系统,传送

NVIC 共支持 1 至 240 个外部中断输入(通常外部中断写作 IRQn),每个中断有最高256(最低8)级的优先级,具体的中断数和优先级级数由芯片厂商在设计芯片时决定(STM32F1支持60个外部中断,16级优先级)。此外,NVIC 还支持一个“永垂不朽”的不可屏蔽中断(NMI)输入。NMI 的实际功能亦由芯片制造商决定。在某些情况下,NMI 无法由外部中断源控制。

NVIC相关寄存器

在内核文件core_cm3.h中定义了NVIC相关的寄存器,

/** @addtogroup CMSIS_CM3_NVIC CMSIS CM3 NVIC
  memory mapped structure for Nested Vectored Interrupt Controller (NVIC)
  @{
 */
typedef struct
{
  __IO uint32_t ISER[8];                      /*!< Offset: 0x000  Interrupt Set Enable Register           */
       uint32_t RESERVED0[24];                                   
  __IO uint32_t ICER[8];                      /*!< Offset: 0x080  Interrupt Clear Enable Register         */
       uint32_t RSERVED1[24];                                    
  __IO uint32_t ISPR[8];                      /*!< Offset: 0x100  Interrupt Set Pending Register          */
       uint32_t RESERVED2[24];                                   
  __IO uint32_t ICPR[8];                      /*!< Offset: 0x180  Interrupt Clear Pending Register        */
       uint32_t RESERVED3[24];                                   
  __IO uint32_t IABR[8];                      /*!< Offset: 0x200  Interrupt Active bit Register           */
       uint32_t RESERVED4[56];                                   
  __IO uint8_t  IP[240];                      /*!< Offset: 0x300  Interrupt Priority Register (8Bit wide) */
       uint32_t RESERVED5[644];                                  
  __O  uint32_t STIR;                         /*!< Offset: 0xE00  Software Trigger Interrupt Register     */
}  NVIC_Type;                                               
/*@}*/ /* end of group CMSIS_CM3_NVIC */

中断使能寄存器 ISER[8] (Interrupt Set-Enable Registers),前面提到CM3 内核支持 256 个中断,这里用 8 个 32 位寄存器来控制,每个位控制一个中断。写1使能该位中断,写0无效。

中断除能寄存器 ICER[8] (Interrupt Clear-Enable Registers),该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。写1清除相应位中断,写0无效。

中断挂起寄存器 ISPR[8] (Interrupt Set-Pending Registers),每个位对应的中断和 ISER 是一样的。通过置 1,可以将正在进行的中断挂起,而执行同级或更高级别的中断。写0无效。

中断解挂寄存器 ICPR[8] (Interrupt Clear-Pending Registers),其作用与 ISPR 相反,对应位也和 ISER 是一样的。写1解挂,写0无效。

中断激活标志位寄存器 IABR[8] (Interrupt Active Bit Registers),只读寄存器,对应位所代表的中断和 ISER 一样,如果为 1,表示该位所对应的中断正在被执行,中断执行完由硬件自动清零。

中断优先级控制的寄存器 IP[240] (Interrupt Priority Registers),与中断分组密切相关,由 240 个 8bit 的寄存器组成,每个可屏蔽中断占用 8bit,最多共可表示 240 个可屏蔽中断(STM32 只用到了其中的前 60 个,IP[59]~IP[0]分别对应中断 59~0)。每个可屏蔽中断占用的 8bit 并没有全部使用,STM32只用了 4位(高四位[7:4],MSB),这 4 位又分为抢占优先级和子优先级,而这两个优先级各占几个位又要根据 SCB->AIRCR 中的中断分组设置来决定

应用中断和复位控制寄存器 SCB_AIRCR

[10:8]位就是中断优先级分组的设置位。

这里再啰嗦一遍

中断优先级配置

中断优先级分组相关函数在misc.c/h文件中

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)//设置中断优先级分组
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) //针对每个特定的中断设置抢占优先级和响应优先级

配置步骤

1.在主函数使用NVIC_PriorityGroupConfig()函数初始化的部分设置中断优先级分组,没有特殊情况的话,一般为分组2,即2位抢占优先级,2位响应优先级。

可选参数

NVIC_PriorityGroup_0 // 0位抢占优先级,4位响应优先级
NVIC_PriorityGroup_1 // 1位抢占优先级,4位响应优先级
NVIC_PriorityGroup_2
NVIC_PriorityGroup_3
NVIC_PriorityGroup_4 // 4位抢占优先级,1位响应优先级

2. 针对每个中断,使用NVIC_Init() 函数设置对应的抢占优先级和响应优先级。

参数为NVIC初始化结构体,其定义如下,包含的参数为:中断请求通道NVIC_IRQChannel、抢占优先级NVIC_IRQChannelPreemptionPriority、响应优先级(亚优先级)NVIC_IRQChannelSubPriority、中断通道使能控制NVIC_IRQChannelCmd。

typedef struct
{
  uint8_t NVIC_IRQChannel;                    /*!< Specifies the IRQ channel to be enabled or disabled.
                                                   This parameter can be a value of @ref IRQn_Type 
                                                   (For the complete STM32 Devices IRQ Channels list, please
                                                    refer to stm32f10x.h file) */

  uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channel
                                                   specified in NVIC_IRQChannel. This parameter can be a value
                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */

  uint8_t NVIC_IRQChannelSubPriority;         /*!< Specifies the subpriority level for the IRQ channel specified
                                                   in NVIC_IRQChannel. This parameter can be a value
                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */

  FunctionalState NVIC_IRQChannelCmd;         /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel
                                                   will be enabled or disabled. 
                                                   This parameter can be set either to ENABLE or DISABLE */   
} NVIC_InitTypeDef;

设置定时器3的抢占优先级举例如下:

主函数中;

 int main(void)
{
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:  2位抢占优先级,2位响应优先级
     //×××_Int_Init();  代码:外设中断配置函数
    while(1)
    {
        //...
    }
}

中断配置函数×××_Int_Init() 中:

×××_Int_Init()
{
    NVIC_InitTypeDef NVIC_InitStructure;	

    //Device Init  代码:外设的初始化配置

    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级3级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器

    //Enable Device   代码:使能外设
}

猜你喜欢

转载自blog.csdn.net/wei348144881/article/details/109002914