完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
STM32 NVIC中断优先级管理
后面用一个具体的例子说明了中断分组、中断线、中断通道的连接关系,先看基本概念: CM3内核支持256个中断,包括16个内核中断和240个外部中断,并且具有256级的可编程中断设置。STM32只使用了一部分CM3内核的东西。STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级。常用的就是这68个可屏蔽中断,但是在STM32F103系列上面只有60个(107系列有68个)。 在MDK内,与NVIC相关的寄存器,MDK为其定义了如下的结构体: typedef struct { vu32 ISER[2]; u32 RESERVED0[30]; vu32 ICER[2]; u32 RSERVED1[30]; vu32 ISPR[2]; u32 RSERVED2[30]; vu32 ICPR[2]; u32 RSERVED3[30]; vu32 IABR[2]; u32 RSERVED4[30]; vu32 IPR[15]; }NVIC_TypeDef; ISER[2]:ISER全称是:Interrupt Set-Enable Registers,这是一个中断使能寄存器组。103系列可屏蔽中断有60个,这里用了2个32位寄存器,总共可以表示64个中断,STM32F103只用了其中的前60位,ISER[0]的bit0~bit31分别对应中断0~31。ISER[1]的bit0~27对应中断32~59;这样,要使能某个中断,必须设置相应的ISER位为1,使该中断被使能(这里仅是使能,还要配合中断分组、屏蔽、IO口映射等设置才算一个完整的中断设置)。 ICER[2]:全称是Interrupt Clear-Enable Registers,是一个清除中断使能寄存器组,和ISER寄存器功能相反。这里专门设置一个ICER寄存器来清除中断位,而不是向ISER写0来擦除,是因为NVIC的这些寄存器都是写1有效的,写0是无效的。 ISPR[2]:全程是Interrupt Set-Pending Registers,是一个中断挂起控制寄存器组。每个位对应的中断和ISER是一样的,通过置1,可将正在进行中的中断挂起,而执行同级或更高级别的中断,写0无效。 ICPR[2]:Interrupt Clear-Pending Registers,解除中断挂起。写1有效,写0无效。 IABR[2]:Interrupt Active Bit Registers,中断激活标志位寄存器组,只读,可以读取当前正在执行的中断是哪一个。在中断执行完成后由硬件自动清零。对应位所代表的中断和ISER相同,如果为1,表示该位所对应的中断正在执行。 IPR[15]:Interrupt Priority Registers,中断优先级控制寄存器组。STM32的中断分组与这个寄存器密切相关。因为STM32的中断多达60多个,所以STM32采用中断分组的办法来确定中断的优先级。IPR寄存器由15个32bit的寄存器组成,每个可屏蔽中断占8bit,这样总共可以表示15x4=60个可屏蔽中断。IPR[0]的[31~24],[23~16],[15~8],[7~0]分别对应中断3~0,总共对应60个外部中断。而每个可屏蔽中断占用的8bit并没有全部使用,只用了高4位。这4位又分为抢占优先级和子优先级。这两个优先级要根据SCB->AIRCR中中断分组的设置来决定。 简单介绍STM32的中断分组:STM32将中断分为0~4共5个组,该组是由SCB->AIRCR寄存器的bit10~8来定义的。如下表所示: 表1 AIRCR中断分组设置表 ———————————————— 版权声明:本文为CSDN博主「LimTian」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/tianshaolin12/article/details/79803838 [tr]组AIRCR[10:8]bit[7:4]分配情况分配结果[/tr]
具体优先级的确定和嵌套规则: * 1 只能高抢先优先级的中断可以打断低抢占优先级的中断服务,构成中断嵌套。 * 2 当2个(N个)相同抢占优先级的中断出现,他们之间不能构成中断嵌套,但STM32首先响应子优先级高的中断。 * 3 当2个(N个)个抢占优先级和子优先级相同的中断出现,STM32首先响应中断同道所对应的中断向量地址低的中断,就是谁先发生谁先被执行。 中断线: STM32的每个IO口都可以作为外部中断的输入口,以F407为例,407的中断控制器支持22个外部中断请求, EXTI线0~15:对应外部IO口的输入中断。 EXTI线16:连接到PVD输出。 EXTI线17:连接到RTC闹钟事件。 EXTI线18:连接到USB OTG FS唤醒事件。 EXTI线19:连接到以太网唤醒事件。 EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件。 EXTI线21:连接到RTC入侵和时间戳事件。 EXTI线22:连接到RTC唤醒事件。 IO口使用的中断线只有16个,但stm32的IO口却不止16个,这些中断线和IO口通过以下关系对应起来: PA0、PB0、PC0…共用EXTI0中断标志,这样每个中断标志只能接收1个外部中断源的信号,如果接入多个IO作为中断源,只有最后配置的一个IO有效,硬件原理图设计时需要注意。EXTI0~EXTI4这5个外部中断有着自己单独的中断号(中断服务函数),EXTI5-9共用一个中断服务函数,EXTI10-15共用一个中断服务函数。可以看到Stm32f10x.h头文件中声明的中断号: 如何使用库函数实现中断分组设置及中断优先级管理: * 1 配置中断优先级分组函数NVIC_PriorityGroupConfig。分组0~4,几位抢占优先级几位子优先级,在系统中只能被调用一次,一旦分组确定就不要修改。 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 2 设置好系统中断分组,对于每个中断,要设置具体的抢占优先级和子优先级的配置。可以通过NVIC_Init函数初始化,其函数声明为: 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; 贴一段外部中断的例程来分析: //外部中断初始化函数 void EXTIX_Init(void) { EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断,需要使能AFIO时钟 KEY_Init();//初始化按键对应io模式 //三个按键分别连到了PC5、PA15、PA0,以下对三个引脚进行配置 //GPIOC.5 中断线以及中断初始化配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5); EXTI_InitStructure.EXTI_Line=EXTI_Line5;//上面说了PA0,PB0为EXTI0,这里PC5中断线应该为EXTI5 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 //GPIOA.15 中断线以及中断初始化配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15); EXTI_InitStructure.EXTI_Line=EXTI_Line15; // PA15中断线为EXTI15 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 //GPIOA.0 中断线以及中断初始化配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); EXTI_InitStructure.EXTI_Line=EXTI_Line0; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键所在的外部中断通道;EXTI0~4单独有自己的中断号(中断服务函数),所以这里是EXTI0。 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //使能按键所在的外部中断通道;EXTI5~9共享一个中断号,所以这里是EXTI9_5_IRQn。 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子优先级1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //使能按键所在的外部中断通道;EXTI10~15共享一个中断号,这里EXTI15的中断号当然是EXTI15_10_IRQn。 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); } |
|||
|
|||
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1754 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1613 浏览 1 评论
1053 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
721 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1667 浏览 2 评论
1931浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
716浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
562浏览 3评论
587浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
546浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-19 15:40 , Processed in 0.623499 second(s), Total 47, Slave 41 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号