STM32F407 NVIC 中断优先级管理 个人笔记

内嵌向量中断控制器:Nested Vectored Interrupt Controller (NVIC)
设置中断向量的优先级并使能。

响应优先级& 抢占优先级

抢占优先级:一个中断A还在处理时,另一个中断B发生,B能否先处理? 答:如果B抢占优先级高就行。
响应优先级:抢占优先级相同时,中断A和中断B同时发生时,先处理哪个? 答:响应优先级高的哪个。
而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。

中断优先级组

是指在寄存器SCB->AIRCR中,配置:
4个位当中,几位是抢占优先级,几位是响应优先级

注意:设置好后不要再改了!以免造成混乱

相关库函数

NVIC相关的库函数在FWLIB的misc.c中

中断优先级分组函数

(一般只调用一次!)
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
例如:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

中断初始化函数

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
其中 NVIC_InitTypeDef 是一个结构体,我们可以看看结构体的成员变量:

typedef struct  
{  
uint8_t NVIC_IRQChannel;  
uint8_t NVIC_IRQChannelPreemptionPriority;  
uint8_t NVIC_IRQChannelSubPriority;  
FunctionalState NVIC_IRQChannelCmd;  
} NVIC_InitTypeDef;  

NVIC_InitTypeDef 结构体中间有三个成员变量,这三个成员变量的作用是:

NVIC_IRQChannel:定义初始化的是哪个中断,这个我们可以在 stm32f4xx.h 中定义的枚举类 型 IRQn
的成员变量中可以找到每个中断对应的名字。例如串口 1 对应 USART1_IRQn。
NVIC_IRQChannelPreemptionPriority:定义这个中断的抢占优先级别。
NVIC_IRQChannelSubPriority:定义这个中断的响应优先级别。
NVIC_IRQChannelCmd:该中断通道是否使能。

比如我们要使能串口 1 的中断,同时设置抢占优先级为 1,响应优先级位 2,初始化的方法是:

NVIC_InitTypeDef NVIC_InitStructure;;  
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口 1 中断  
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 抢占优先级为 1  
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 响应优先级位 2  
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能  
NVIC_Init(&NVIC_InitStructure); //根据上面指定的参数初始化 NVIC 寄存器

编程步骤

最简单的应用中,只要

  1. 设置分组
  2. 外设中断使能(函数名在外设的头文件中有)
  3. 初始化
  4. 写中断服务函数(函数名在setup巴拉巴拉中定义)
    即可:
//1.
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);   //可能在主函数
//2.
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);             //可能在初始化函数中
//3.
NVIC_InitTypeDef NVIC_InitStructure;     / /可能在初始化函数
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口 1 中断  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 抢占优先级为 1  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 响应优先级位 2  
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能  
    NVIC_Init(&NVIC_InitStructure); //根据上面指定的参数初始化 NVIC 寄存器
//4.中断服务函数
void USART1_IRQHandler(void)
{
}

上面是一些常用的东西,下面是其他一些有的没的

支持的中断数量

  • CM4内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。
  • STM32F4并没有使用CM4内核的全部东西,而是只用了它的一部分。
    STM32F40xx/STM32F41xx总共有92个中断。
    STM32F42xx/STM32F43xx则总共有96个中断
  • STM32F40xx/STM32F41xx的92个中断里面,包括10个内核中断和82个可屏蔽中断,具有16级可编程的中断优先级,而我们常用的就是这82个可屏蔽中断。

中断设置相关的寄存器

__IO uint8_t  IP[240]; //中断优先级控制的寄存器组

__IO uint32_t ISER[8]; //中断使能寄存器组

__IO uint32_t ICER[8]; //中断失能寄存器组

__IO uint32_t ISPR[8]; //中断挂起寄存器组

__IO uint32_t ICPR[8]; //中断解挂寄存器组

__IO uint32_t IABR[8]; //中断激活标志位寄存器组

中断优先级控制寄存器组:IP[240]

Interrupt Priority Registers
240个8位寄存器
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
例如:NVIC_Init(&NVIC_InitStructure);

中断使能寄存器组:ISER[8]

8个32位寄存器(CM4内核支持256个中断)
每个位控制一个中断的使能
STM32F40x只有82个可屏蔽中断,所以只使用了其中的ISER[0]~ISER[2]。

ISER[0]的bit031分别对应中断0-31
ISER[1]的bit0-27对应中断32-63;
ISER[2]的bit0-17对应中断64~81;

posted @ 2018-11-26 17:03  YuQiao0303  阅读(2765)  评论(0编辑  收藏  举报