完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
NVIC 中断优先级管理
Nested Vectored Interrupt Controller,嵌套向量中断控制器。 CM3支持256个中断,16个内核中断,240个外部中断,256级可编程中断设置。 STM32使用了其中一部分,16个内核中断,107系列有68个可屏蔽中断(103系列只有60个),16级可编程的中断优先级。 中断寄存器 ISER[8],Interrupt Set-Enable Registers,中断使能寄存器组,用8个32位寄存器控制(256个可编程中断),每个位控制一个中断。由于STM32f103只有60个可屏蔽中断,于是只用了 ISER[0] 和 ISER[1] 64个中断中的前60位。 ISER[0] 的 bit0 至 bit31 对应中断0至31,ISER[1] 的 bit0 至 bit27 对应中断32至59,使能某个中断就将对应的 ISER 置1 ICER[8],Interrupt Clear-Enable Register,中断除能寄存器组。中断对应与ISER相同,但作用是置1清除中断使能 ISPR[8],Interrupt Set-Pending Register,中断挂起控制寄存器组。置1将正在进行的中断挂起,暂停等待执行,执行同级或更高级别的中断 ICPR[8],Interrupt Clear-Pending Register,中断解挂控制寄存器组,置1将挂起的中断解挂 IABR[8],Interrupt Active Bit Register,中断激活标志位寄存器组,只读寄存器,为1表示该位对应的中断正在被执行 IP[240],Interrupt Priority Registers,中断优先级控制寄存器组,相当重要! STM32的中断分组与其密切相关。 IP[240]有240个8bit寄存器组成,每个可屏蔽中断占用8bit,总共可表示240个可屏蔽中断,STM32f1使用其中60个,IP[59]至IP[0]分别对应中断59至0。每个可屏蔽中断只用高4位,分为抢占优先级和响应优先级,抢占优先级在前、响应优先级在后,各占几位由SCB-》AIRCR中的中断分组设置。采用库函数==NVIC_PriorityGroupConfig () ==配置。 如果组设置为3,则每个中断的中断优先寄存器高4位中前3位是抢占优先级,优先级级别0-7;低1位是响应优先级,优先级级别0-1。 STM32的中断向量有抢占属性和响应属性,属性编号越小,优先级别越高。 抢占属性是打断其他中断的属性,有这个属性就有嵌套中断。由库函数NVIC_IRQChannelPreemptionPriority() 进行参数配置。 响应属性应用在抢占属性相同时(前提),两个中断向量的抢占优先级相同时,如果同时到达,则优先处理响应优先级高的中断。由库函数NVIC_IRQChannelSubPriority() 进行参数配置。 库函数配置 NVIC 中断管理函数声明在 misc.c 文件里 1. 中断优先级分组函数 NVIC_PriorityGroupConfig() 此函数在系统工程中只能被调用一次!一旦确定好中断分组就不能更改! 目前了解到的在主函数中调用该函数 按 F12 查看函数定义块: void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) { assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup)); SCB-》AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup; } 可以看到,这个函数通过设置 SCB-》AIRCR 寄存器设置中断分组。 补充: assert_param(),断言机制函数,在stm32f10x_conf.h文件中可以看到 assert_param() 是一个宏定义,作用就是检测传递给函数的参数是否是有效的参数,返回值是 0假 1真。 中断优先组配置示例:分组值为2,2优先2抢占: 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; NVIC_IRQChannel,定义初始化的是哪个中断,例如 USART1_IRQn NVIC_IRQChannelPreemptionPriority,定义这个中断的抢占优先级别,级别数不超过2的“抢占优先级位数”次方。(一个是位数,一个是级别数) NVIC_IRQChannelSubPriority,定义这个中断的响应优先级别,级别数不超过2的“响应优先级位数”次方。 NVIC_IRQChannelCmd,该中断是否使能 IRQ全称为Interrupt Request,即是“中断请求”的意思 中断初始化配置示例: 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 寄存器 通常如果写外部中断时,此代码块放在 exti.cEXTI_Init() 函数内部,每个端口配置结束都需要一个NVIC_Init(&NVIC_InitStructure); 小结 中断优先级设置的步骤: 系统运行开始的时候设置中断分组。确定组号,也就是确定抢占优先级和子优先级的分配位数。调用函数为 NVIC_PriorityGroupConfig(); 设置所用到的中断的中断优先级别,对每个中断调用函数为 NVIC_Init(); STM32 外部中断 基础知识 STM32 外部 IO 口的中断功能 文件: stm32f10x_exti.c/h 每个 IO 口都可以作为外部中断的中断输入口,支持19个外部中断/事件请求,每个中断设有状态位、独立的触发/屏蔽设置。 19个外部中断为: 线 0-15:对应外部 IO 口的输入中断 (供 IO 口使用的中断线) 线 16 :连接到PVD输出(Programmable Votage Detector,可编程电压监测器) 线 17 :连接到RTC闹钟事件 线 18 :连接到USB唤醒事件 映射方式: 每个中断线对应最多7个IO口,但每次只能连接到一个IO口上,利用选择器的配置来决定中断线配置到哪个IO口上去。 库函数配置 1. 映射关系配置 GPIO_EXTILineConfig() 外部中断端口映射配置示例 (GPIOE_2 与 EXTI_2): GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2); 2. 中断初始化 EXTI_Init() void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct); //结构体函数参数 查看一下结构体: typedef struct { uint32_t EXTI_Line; EXTIMode_TypeDef EXTI_Mode; EXTITrigger_TypeDef EXTI_Trigger; FunctionalState EXTI_LineCmd; }EXTI_InitTypeDef; 有4个需要设置的参数: 中断线标号,EXTI_Line0~EXTI_Line15 中断模式,中断 EXTI_Mode_Interrupt 和事件 EXTI_Mode_Event 触发方式,下降沿触发 EXTI_Trigger_Falling,上升沿触发 EXTI_Trigger_Rising,任意电平(上升沿和下降沿)触发EXTI_Trigger_Rising_Falling 使能,ENABLE 中断和事件的区别 简而言之,中断是需要经过芯片内部程序处理,然后跳转的中断程序 事件是检测到某一动作(电平边沿)触发事件发生了,进而由提前设置好的相应的联动硬件自动完成产生的结果 中断是红线 事件是绿线 外部中断初始化配置示例: EXTI_InitTypeDef EXTI_InitStructure; //定义结构体 EXTI_InitStructure.EXTI_Line=EXTI_Line4; //中断线4 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 寄存器 3. 设置中断线2的中断优先级 优先级配置见第一部分NVIC的配置 NVIC_InitTypeDef NVIC_InitStructure; //定义NVIC结构体 NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能按键外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //响应优先级 2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); //中断优先级分组初始化 4. 中断服务函数 STM32一共15个IO口外部中断线,共有6个中断函数: EXPORT EXTI0_IRQHandler EXPORT EXTI1_IRQHandler EXPORT EXTI2_IRQHandler EXPORT EXTI3_IRQHandler EXPORT EXTI4_IRQHandler EXPORT EXTI9_5_IRQHandler EXPORT EXTI15_10_IRQHandler 0-4每个中断线对应一个中断函数,5-9共用EXTI9_5_IRQHandler,10-15共用EXTI15_10_IRQHandler 当多线共用一个处理函数的时候,就必须写EXTI_GetITStatus()判断到底是哪一线中断请求 1. ITStatus EXTI_GetITStatus(); 用在中断服务函数的开头,判断中断是否发生 EXTI_GetFlagStatus()与之的区别 EXTI_GetITStatus() 函数中会先判断这种中断是否使能,使能了才去判断中断标志位 而EXTI_GetFlagStatus() 直接用来判断状态标志位 2. EXTI_ClearITPendingBit(EXTI_Line0); 中断服务函数结束之前调用,清除某中断线上的中断标志位 EXTI_ClearFlag(),与之功能相同 常用的中断服务函数格式: void EXTI2_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line2)!=RESET) //判断某个线上的中断是否发生 { 中断逻辑… EXTI_ClearITPendingBit(EXTI_Line2); //清除 LINE 上的中断标志位 } } 外部中断配置示例 1. exit.c 包含4个函数: EXTI_Init() 外部中断初始化,(以按键功能为例): void EXTIX_Init(void) { EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //调用结构体 调用 KEY_Init 函数,来初始化外部中断输入的 IO 口。 KEY_Init();//初始化按键对应 io 模式 2.调用RCC_APB2PeriphClockCmd()函数来使能复用功能时钟。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //外部中断,需要使能 AFIO 时钟 4.接着配置中断线和 GPIO 的映射关系。 //GPIOC.5 与中断线5映射 GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5); 5.然后初始化中断线。 EXTI_InitStructure.EXTI_Line=EXTI_Line5; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); 6.中断初始化、配置优先级 NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); EXTI0_IRQHandler() 中断处理函数 void EXTI0_IRQHandler(void) { delay_ms(10); if(WK_UP==1)//WK_UP在key.h文件中定义 { LED0=!LED0;//LED0在led.h文件中定义 LED1=!LED1; } EXTI_ClearITPendingBit(EXTI_Line0); //清除EXTI0线路挂起位 } EXTI9_5_IRQHandler() EXTI15_10_IRQHandler() 小结 使用 IO 口外部中断的一般步骤: 初始化 IO 口为输入。 开启 IO 口复用时钟,设置 IO 口与中断线的映射关系。 初始化线上中断(EXTI),设置触发条件等。 配置中断分组(NVIC),并使能中断。 编写中断服务函数。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试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:17 , Processed in 0.908712 second(s), Total 78, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号