STM32-NVIC中断优先级分组-中断优先级设置
STM32-中断优先级管理NVIC
1.NVIC中断优先级分组
NVIC的全称是Nested vectoredinterrupt controller,即嵌套向量中断控制器。STM32F中⽂参考⼿册中搜索向量表可以找到相应的中断说明。
CM4/CM7 内核⽀持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。
STM32F4/F7并没有使⽤CM4内核的全部东西,⽽是只⽤了它的⼀部分。
STM32F40xx/STM32F41xx总共有92个中断。10个内核中断,82个可屏蔽中断。
STM32F42xx/STM32F43xx则总共有97个中断。10个内核中断,87个可屏蔽中断。
STM32F76x总共118个中断,10个内核中断,108个可屏蔽中断。
STM32具有16级可编程的中断优先级,⽽我们常⽤的就是这些可屏蔽中断。
⼏⼗个中断,怎么管理?
⾸先,对STM32中断进⾏分组,组0~4。同时,对每个中断设置⼀个抢占优先级和⼀个响应优先级值。
分组配置是在寄存器SCB->AIRCR中配置: IP bit[7:4]有4位,2^4=16,所以说它们的优先级可以有16个值,这时候如果是2位抢占优先级,那么它的值可能为0、1、2、3。也就是抢占优先级可以取0到3 。⾸先进⾏分组来决定⼏位抢占优先级、⼏位响应优先级。数越⼩它的优先级越⾼。
组AIRCR[10:8]IP bit[7:4]分配情况分配结果
英语小笑话01110:40位抢占优先级,4位响应优先级
11101:31位抢占优先级,3位响应优先级
21012:22位抢占优先级,2位响应优先级
31003:13位抢占优先级,1位响应优先级
40114:04位抢占优先级,0位响应优先级
抢占优先级 & 响应优先级区别:
⾼优先级的抢占优先级是可以打断正在进⾏的低抢占优先级中断的。抢占决定了是否能打断别⼈。
抢占优先级相同的中断,⾼响应优先级不可以打断低响应优先级的中断。
抢占优先级相同的中断,当两个中断同时发⽣的情况下,哪个响应优先级⾼,哪个先执⾏。
幼儿园教师发言稿如果两个中断的抢占优先级和响应优先级都是⼀样的话,则看哪个中断先发⽣就先执⾏;
举例:
假定设置中断优先级组为2,然后设置
我的梦想
中断3(RTC中断)的抢占优先级为2,响应优先级为1。
中断6(外部中断0)的抢占优先级为3,响应优先级为02015上海高考数学
中断7(外部中断1)的抢占优先级为2,响应优先级为0。
那么这3个中断的优先级顺序为:中断7>中断3>中断6。
⼀般情况下,系统代码执⾏过程中,只设置⼀次中断优先级分组,⽐如分组2,设置好分组之后⼀般不会再改变分组。随意改变分组会导致中断管理混乱,程序出现意想不到的执⾏结果。
中断优先级分组函数位于HALLIB中的stm32f7xx_hal_cortex.c:void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup);
void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
/* Check the parameters */
asrt_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
/* Set the PRIGROUP[10:8] bits according to the PriorityGroup parameter value */
NVIC_SetPriorityGrouping(PriorityGroup);
}
可以找到IS_NVIC_PRIORITY_GROUP的定义,进⽽确定PriorityGroup参数怎么写。
#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))
在stm32f7xx_hal.c中可以找到HAL_Init函数:其中HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);可以看到中断分组为2 。HAL_StatusTypeDef HAL_Init(void)
{
/* Configure Flash prefetch and Instruction cache through ART accelerator */
#if (ART_ACCLERATOR_ENABLE != 0)
__HAL_FLASH_ART_ENABLE();
#endif /* ART_ACCLERATOR_ENABLE */
/* Set Interrupt Group Priority */
ui设计培训机构好HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
/* U systick as time ba source and configure 1ms tick (default clock after Ret is HSI) */
钩吻海蛇HAL_InitTick(TICK_INT_PRIORITY);
/* Init the low level hardware */
HAL_MspInit();
/* Return function status */
return HAL_OK;
}
2.NVIC中断优先级设置
分组设置好之后,怎么设置单个中断的抢占优先级和响应优先级?
中断设置相关寄存器:
_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]; //中断激活标志位寄存器组
位于core_cm7.h中:NVIC_Type结构体中成员变量就是那些寄存器。
/**
\brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
*/
typedef struct
{
__IOM uint32_t ISER[8U]; /*!< Offt: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[24U];
exists__IOM uint32_t ICER[8U]; /*!< Offt: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[24U];
__IOM uint32_t ISPR[8U]; /*!< Offt: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[24U];
__IOM uint32_t ICPR[8U]; /*!< Offt: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[24U];
__IOM uint32_t IABR[8U]; /*!< Offt: 0x200 (R/W) Interrupt Active bit Register */
uint32_t RESERVED4[56U];
__IOM uint8_t IP[240U]; /*!< Offt: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
uint32_t RESERVED5[644U];
__OM uint32_t STIR; /*!< Offt: 0xE00 ( /W) Software Trigger Interrupt Register */
} NVIC_Type;
对于每个中断怎么设置优先级?
中断优先级控制的寄存器组:IP[240],全称是:Interrupt Priority Registers
240个8位寄存器,每个中断使⽤⼀个寄存器来确定优先级。STM32F40x系列⼀共82个可屏蔽中断,使⽤IP[81]~IP[0]。
每个IP寄存器的⾼4位⽤来设置抢占和响应优先级(根据分组),低4位没有⽤到。
在stm32f7xx_hal_cortex.c可找到:
学外语/**
* @brief Sets the priority of an interrupt.
* @param IRQn: External interrupt number.英译汉在线翻译
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, plea refer to the appropriate CMSIS device file (stm32f7xxxx.h))
* @param PreemptPriority: The preemption priority for the IRQn channel.
* This parameter can be a value between 0 and 15
* A lower priority value indicates a higher priority
* @param SubPriority: the subpriority level for the IRQ channel.
* This parameter can be a value between 0 and 15
* A lower priority value indicates a higher priority.
* @retval None
*/
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority) {
uint32_t prioritygroup = 0x00;
/* Check the parameters */
asrt_param(IS_NVIC_SUB_PRIORITY(SubPriority));
asrt_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));
prioritygroup = NVIC_GetPriorityGrouping();
NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority)); }
中断优先级设置步骤:
系统运⾏后在HAL_Init函数中设置中断优先级分组。调⽤函数:
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
//中断优先级分组2 整个系统执⾏过程中,只设置⼀次中断分组。
针对每个中断,设置对应的抢占优先级和响应优先级:
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t
PreemptPriority, uint32_t SubPriority);
使能中断通道:
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
{
/* Check the parameters */
asrt_param(IS_NVIC_DEVICE_IRQ(IRQn));
/
* Enable interrupt */
NVIC_EnableIRQ(IRQn);初花
}