完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
最近有网友经实验验证( 网友的验证.),Systick虽然作为与CPU紧耦合的内核外设,但其中断优先级并不比普通外设要高,并不因为它是内核外设而特殊,它还是遵循中断优先级高低的规则来响应。就网友的结论是没问题,但网友的实验现象感觉有点出入,和自己想的不太一样,出严谨,按网友的代码在stm32f103的芯片是实验了一下,由于网友的是stm32f429IGT6的芯片,程序上会有点不一样,但都是stm32系列的想来问题不大,同事我的项目是用M3的芯片,探究也是M3的内外中断的区别,终于还是用M3的来验证吧。
实验环境条件如下:MDK v5.30.0.0,STM32F103C8T6的MCU。 设置Systick的中断优先级为7(1,3),100ms产生一个中断,初始化Systick代码如下: v void delay_init() { // SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8 // fac_us=SystemCoreClock/8000000; //为系统时钟的1/8 if (SysTick_Config(SystemCoreClock / 10)) { /* Capture error */ while (1); } } static __INLINE uint32_t SysTick_Config(uint32_t ticks) { if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */ // NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */ NVIC_SetPriority (SysTick_IRQn, 7); /* set Priority for Cortex-M0 System Interrupts */ SysTick->VAL = 0; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0); /* Function successful */ } Systick的中断服务函数如下: void SysTick_Handler(void) { LED_SYS=!LED_SYS; Delayms(5);//普通的软件延时 } void Delayms(u16 ms) { u16 i,j; u8 k; for(i=0;i } 然后配置两个按键KEY0和KEY1,产生两个外部中断EXTI(下降沿触发),NVIC的Group分组为 Group2。分别设置KEY0的外部中断优先级为15(2,2),KEY2的外部中断优先级为3(0,2),代码如下: //外部中断0服务程序 void EXTIX_Init(void) { EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; KEY_Init(); // 按键端口初始化 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能复用功能时钟 //GPIOE.2 中断线以及中断初始化配置 下降沿触发 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); EXTI_InitStructure.EXTI_Line=EXTI_Line0; //KEY1 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寄存器 //GPIOE.3 中断线以及中断初始化配置 下降沿触发 //KEY1 GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1); EXTI_InitStructure.EXTI_Line=EXTI_Line1; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键WK_UP所在的外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; //使能按键KEY2所在的外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; //抢占优先级2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); } //按键初始化函数 void KEY_Init(void) //IO初始化 { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);//使能PORTA,PORTE时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//KEY0 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA0,GPIOB1 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//KEY1 GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOA0,GPIOB1 } KEY0和KEY1的外部中断服务函数如下: //外部中断0服务程序 void EXTI0_IRQHandler(void) { Delayms(10);//消抖 if(KEY0==0&&EXTI_GetITStatus(EXTI_Line0) != RESET) //WK_UP按键 { LED_R=!LED_R; while(1) { Delayms(10); } } EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位 } //外部中断1服务程序 void EXTI1_IRQHandler(void) { Delayms(10);//消抖 if(KEY1==0&&EXTI_GetITStatus(EXTI_Line1) != RESET) //按键KEY2 { LED_W=!LED_W; while(1) { Delayms(10); } } EXTI_ClearITPendingBit(EXTI_Line1); //清除LINE2上的中断标志位 } 最后是主函数的代码: int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 delay_init(); //延时函数初始化 uart_init(115200); //串口初始化为115200 LED_Init(); //初始化与LED连接的硬件接口 BEEP_Init(); //初始化蜂鸣器端口 // KEY_Init(); //初始化与按键连接的硬件接口 EXTIX_Init(); //外部中断初始化 while(1) { printf("OKrn"); // delay_ms(1000); } } 实验设计的条件如下: [tr]中断KEY0SystickKEY1[/tr]
实验现象如下: 程序下到板子里开始跑后,未操作前,一直绿灯闪烁,当第一次按下按键0后,会亮红灯,再按按键0,无反应(还是亮红灯绿灯闪烁);然后按下按键1,亮白灯,一直亮白灯,再按按键1,无反应(还是亮白灯且红灯亮,绿灯不在闪烁)。 实验现象分析: 未操作前,亮红灯,因为每100ms产生一次Systick中断,绿灯状态改变一次,呈现绿灯闪烁; 当按下KEY0后,会亮红灯然后绿灯闪烁,这是因为KEY0的中断优先级虽然比Systick低,但是当执行完Systick中断后还是会去执行KEY0的中断,称为“咬尾中断”,然后当Systick产生中断后再返回Systick中断;再按KEY0,无反应,是因为代码中在退出按键1中断前加了个死循环,未清除KEY0的中断标志位,所以进不去; 然后按下KEY1,一直亮白灯和红灯,绿灯不在闪烁。是因为KEY1的中断优先级比Systick高和KEY0的中断,能抢占,而且KEY1的中断里也加了个死循环,退不出来。也就是说,当KEY1的中断在执行的时候,虽然Systick的时间到了,产生了Systick中断,但还是打断不了KEY1的中断,因为优先级没它(KEY1)高。 实验结论: Systick虽然作为与CPU紧耦合的内核外设,但其中断优先级并不比普通外设要高,并不因为它是内核外设而特殊,它还是遵循中断优先级高低的规则来响应。 实验注意: 设置Systick中断优先级的时候,不能通过修改__NVIC_PRIO_BITS的大小,比如改成3,使Systick中断优先级为7;同时内核的中断优先级的寄存器和外设中断优先级的存储寄存器不同,不能用设置外设中断优先级的方法设置内核中断优先级,而应该和上面代码一样,采用直接赋值的办法。因为__NVIC_PRIO_BITS表示的是M3所有中断分组所用的位数,不是普通的设置成Systick中断优先级的数字; 另外,NVIC分组设置,最好设置为Group2,两位表示抢占优先级(主优先级),两位表示响应优先级(子优先级),方便对比。 同时如果写的程序没有调用SysTick_Config()函数也就是没调用NVIC_SetPriority() 函数,程序的优先级会默认为0(不管是内核中断还是外设中断,只要没设置中断优先级,中断优先级都默认为0,同为0级后优先按官方手册中的中断排列顺序来)。在一些带UCOSII的stm32案例中是没有调用NVIC_SetPriority() 函数的,但SysTick中断的优先级不是0,而是15,这是因为UCOSII系统的官方代码中,用汇编对SysTick中断寄存器进行了优先级设置,和st官方NVIC_SetPriority() 函数是一样的。 汇编对SysTick中断寄存器进行了优先级设置见下图: 1.未设置SysTick中断寄存器 2.设置SysTick中断寄存器后 实验搭建的硬件平台: |
|||
|
|||
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
728浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
568浏览 3评论
593浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 14:43 , Processed in 0.843817 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号