CM3 内核支持 256 个中断,STM32 并没有使用 CM3 内核的全部只用了它的一部分。
STM32 有 84 个中断,包括 16 个内核中断和 68 个可屏蔽中断,STM32F103 系列上面只有 60 个(107 系列才有 68 个)。下面针对STM32F103 系列说明。
与 NVIC 相关的寄存器中IPR[15]:是一个中断优先级控制的寄存器组由15个32bit的寄存器组成.
每一个可屏蔽中断对应8bit。所以每一个32bit寄存器对应4个可屏蔽中断:15*4=60。
IPR[0]的[31~24], [23~16], [15~8], [7~0]分别对应 3~0,4个可屏蔽中断,依次类推,总共对应 60 个外部中断。
每个中断对应的8bit只使用了高4位。这4位又分为抢占优先级和子优先级。抢占优先级和子优先级各占几位由SCB->AIRCR 寄存器的 bit7~4来定义的。
STM32 又将中断分为 5 个组,组 0~4。该分组的设置是由 SCB->AIRCR 寄存器的 bit10~8 来定义的。具体的分配关系如表 所示:
例如组设为3,那么所有的60个中断,每个中断对应的寄存器高3位是抢占优先级,低1位数响应优先级。3位抢占优先级可以选择0~7,8种情况。1位响应优先级可以选择0或1两种选择。抢占优先级别高于响应优先级别,数值越小代表的优先级就越高。
优先级的工作情况:
1、当抢占优先级和响应优先级一样时,哪个中断先发生就执行哪个。
2、高优先级的抢占优先级中断可以打断低优先级的抢占优先级中断
3、抢占优先级相同时,高优先级的响应优先级中断不可以打断低优先级的响应优先级中断。
例如:
1、设置中断优先级组为2。2位抢占优先级(0~4),2位响应优先级(0~4)
2、设置中断3(RTC 中断)的抢占优先级为 2,响应优先级为 1。
3、设置中断 6(外部中断 0)的抢占优先级为 3,响应优先级为 0。
4、设置中断 7(外部中断 1)的抢占优先级为 2,响应优先级为 0。
那么这 3 个中断的优先级顺序为:中断 7>中断 3>中断 6。中断7和3可以打断中断6,中断3和7不可以打断对方。
中断优先级设置的步骤:
1、系统运行开始时设置中断分组。确定组号,也就是确定抢占优先级和子优先级的分配位数。 调用函数为 void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
可以看出设置中断分组就是设置SCB->AIRCR寄存器。
2、设置所用到的中断的中断优先级别。 对每个中断调用中断初始化函数为
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
结构体参数:
typedef struct
{uint8_t NVIC_IRQChannel;//定义初始化的是哪个中断
uint8_t NVIC_IRQChannelPreemptionPriority;//定义这个中断的抢占优先级别
uint8_t NVIC_IRQChannelSubPriority;//定义这个中断的子优先级别。
FunctionalState NVIC_IRQChannelCmd;//该中断是否使能。
} NVIC_InitTypeDef;
例如:我们设置中断优先级分组值为2,
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
使能串口 1 的中断,同时设置抢占优先级为 1,子优先级位 2,
USART_InitTypeDef USART_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 寄存器