大家好,又见面了,我是你们的朋友全栈君。
使用中断之前,第一步要了解的是其优先级管理,下面总结一下STM32 NVIC的中断优先级管理。(正点原子系列)
以smt32f103系列为例,其具有16个内核中断和60个可屏蔽中断。 下面介绍其库函数的开发:
MDK内与NVIC相关的寄存器包含在结构体中,通过创建结构体,配置其内部组成员也就是寄存器,来配置NVIC各个配置。
先介绍其结构体的内部内容:在结构体内有介绍!
中断配置寄存器
[ ]内的8表示有8个这样的寄存器!
代码语言:javascript复制typedef struct
{
//[ ]内8表示有8个寄存器,每个都是32位,总计256个位,每个位控制一个中断,最高支持256个!
// offest 表示地址
__IO uint32_t ISER[8]; /*!< Offset: 0x000 打开中断的使能寄存器 */
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; /*!< Offset: 0x080 清除的中断使能的寄存器 */
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; /*!< Offset: 0x100 把中断挂起的寄存器(就是暂停现在的中断放到一边,执行同级或者更高的中断) */
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; /*!< Offset: 0x180 关闭中断挂起 */
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; /*!< Offset: 0x200 中断标志位,对应位为1则表示对应中断正在执行,为0则未执行,中断执行完成后自动置0 */
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; /*!< Offset: 0x300 240个8位寄存器组成,配置240个可屏蔽中断,8位长度,只使用了高4位,用来配置抢占优先级和子优先级,两者分别占一定的长度来配置,具体长度由SCB->AIRCR的中断分组来确定 */
uint32_t RESERVED5[644];
__O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */
} NVIC_Type;
中断分组:
将中断分为5组,每组有对应的抢占优先级和子优先级。 由寄存器SCB->AIRCR寄存器的位8-10来定义的!具体配置参考下图:
关于优先级,注意一下两点: 这里需要注意两点:第一,如果个中断的抢占优先级和响应都是样话则看哪个中断先发生就先执行;第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。
以上就是原理的一点总结了,下面到使用中断时库函数的配置:
配置中断三步走: 第一!分组配置优先级在AIRCR中的分配位数! 第二!配置结构体内需要用到的成员 、什么中断 、什么抢占优先级、 什么子优先级 、是否使能 ! 第三!将结构体首地址传入,装载配置!
分组
代码语言:javascript复制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;
}
//IS_NVIC_PRIORITY_GROUP详解
#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) ||
((GROUP) == NVIC_PriorityGroup_1) ||
((GROUP) == NVIC_PriorityGroup_2) ||
((GROUP) == NVIC_PriorityGroup_3) ||
((GROUP) == NVIC_PriorityGroup_4))
中断的分组直接通过void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)传参传入NVIC_PriorityGroup_X对应的值就行。
配置
通过结构体配置(如下) typedef struct { uint8_t NVIC_IRQChannel; /* 定义初始化的是哪个中断,这个我们可以在 stm32f10x.h 中找到 每个中断对应的名字。例如 USART1_IRQn*/
uint8_t NVIC_IRQChannelPreemptionPriority; /定义这个中断的抢占优先级别。/
uint8_t NVIC_IRQChannelSubPriority; /* 定义这个中断的子优先级别。*/
FunctionalState NVIC_IRQChannelCmd; /*该中断是否使能 */ } NVIC_InitTypeDef;
传入参数
通过下面函数传址,把配置的结构体传入寄存器中, void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
样例:
比如我们要使能串口 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 寄存器
OVER!
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/140696.html原文链接:https://javaforall.cn