找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5187|回复: 7
收起左侧

关于stm32外部中断时而无法进入的问题分析

[复制链接]
ID:230118 发表于 2020-11-12 16:27 | 显示全部楼层 |阅读模式
搞了几天了,找不到原因,不知各路大神是否有遇到类似问题,提供点建议,问题描述如下:
实现功能如下,根据外部中断EXTI0、EXTI1来改变某个IO的输出电平,当此IO输出电平持续在低电平1ms以上时,触发定时器6,当PD8为低电位时,外部电路隔一段时间后会触发EXTI1, 当PD8为高电位时,又会触发EXTI0 中断

STM32外部中断配置:
  1. void EXTI_Configuration()
  2. {
  3.     EXTI_InitTypeDef EXTI_InitStructure;
  4.     NVIC_InitTypeDef NVIC_InitStructure;
  5. #ifdef   VECT_TAB_RAM
  6.     /* Set the Vector Table base location at 0x20000000 */
  7.     NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
  8. #else   /* VECT_TAB_FLASH   */
  9.     /* Set the Vector Table base location at 0x08000000 */
  10.     NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
  11. #endif

  12.     /* Configure the NVIC Preemption Priority Bits */  
  13.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);


  14.     EXTI_ClearITPendingBit(EXTI_Line0);
  15.     EXTI_ClearITPendingBit(EXTI_Line1);
  16.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource0);
  17.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource1);
  18.     EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;     //选择中断线路0 1


  19.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;         //设置为中断请求,非事件请求
  20.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;     //设置中断触发方式为下降沿触发
  21.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;                   //外部中断使能
  22.     EXTI_Init(&EXTI_InitStructure);
  23.     EXTI->IMR&=~(1|1<<1);

  24.     /*允许EXTI0中断 */
  25.     NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
  26.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  27.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  28.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  29.     NVIC_Init(&NVIC_InitStructure);

  30.     /*允许EXTI1中断 */
  31.     NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
  32.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  33.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  34.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  35.     NVIC_Init(&NVIC_InitStructure);
复制代码
  1. void EXTI0_IRQHandler(void)
  2. {
  3. if (RESET!=(EXTI->PR&EXTI_Line0))
  4. {
  5.         EXTI->PR = EXTI_Line0;
  6.         if (RESET!=(EXTI->IMR&EXTI_Line0))
  7.         {
  8.             TAG.FbCurcuit1 = 1;
  9.             GPIOD->BSRR = GPIO_Pin_8;
  10.             if (0==Hall1)
  11.             {
  12.                 EXTI->IMR&=~(EXTI_Line0);
  13.                 TIM6->SR = (uint16_t)~TIM_IT_Update;
  14.                 TIM6->CR1 &= ((uint16_t)~TIM_CR1_CEN);
  15.                 Hall1 = 1;
  16.             }
  17.             else
  18.             {
  19.                 TIM6->CNT = 0;
  20.                 TIM6->SR = (uint16_t)~TIM_IT_Update;
  21.                 TIM6->CR1 |= TIM_CR1_CEN;
  22.             }
  23.         }
  24.         EXTI->PR = EXTI_Line0;
  25.     }
  26. }

  27. void EXTI1_IRQHandler(void)
  28. {
  29.     if (RESET!=(EXTI->PR&EXTI_Line1))
  30.     {
  31.         EXTI->PR = EXTI_Line1;
  32.         if (RESET!=(EXTI->IMR&EXTI_Line1))
  33.         {
  34.             GPIOD->BRR = GPIO_Pin_8;
  35.             TIM6->SR = (uint16_t)~TIM_IT_Update;
  36.             TIM6->CR1 &= ((uint16_t)~TIM_CR1_CEN);
  37.         }
  38.         EXTI->PR = EXTI_Line1;
  39.     }
  40. }
复制代码

启动这个功能后,运行一段时间后,会进入定时器6的中断,跟踪发现是某个EXTI1中断没有得到执行,检查了所有相关的配置以及设计到相关IO操作的地方,没有发现异常,现贴出部分跟踪数据:

0.png 1.png

在TIM6中断服务程序入口处设置断点,从上面截图中可以看到 EXTI1 中断标志位PR1 是有被置位的, 但EXTI0 EXTI1 最后一次触发时间是418.00248863,  ,而TIM6触发是在 418.00408187, , 可见是因为EXTI1未得到执行从而导致TIM6未关闭而进入了TIM6中断,此时外部中断PR1已经是置位的,为什么EXTI1有发生中断却进不了中断函数呢,而前面却一直可以进去

3.jpg
上图是PE0和PE1的输入,黄色是PE0
外部中断的频率大约100k,工作在72M的stm32f103vct6 应该是可以承受的吧
回复

使用道具 举报

ID:230118 发表于 2020-11-13 18:48 | 显示全部楼层
沉了呀,没有大佬指点下我吗,纠正个错误
“当PD8为低电位时,外部电路隔一段时间后会触发EXTI1, 当PD8为高电位时,又会触发EXTI0 中断”
应为当PD8为低电位时,外部电路隔一段时间后会触发EXTI0, 当PD8为高电位时,又会触发EXTI1 中断
回复

使用道具 举报

ID:230118 发表于 2020-11-13 18:54 | 显示全部楼层
沉了,请大佬们关注指点下,谢谢
纠正个错误:“当PD8为低电位时,外部电路隔一段时间后会触发EXTI1, 当PD8为高电位时,又会触发EXTI0 中断”应为“当PD8为低电位时,外部电路隔一段时间后会触发EXTI0, 当PD8为高电位时,又会触发EXTI1 中断”
回复

使用道具 举报

ID:230118 发表于 2020-11-14 11:26 | 显示全部楼层
谢谢楼上的朋友帮顶,贴出中断优先级配置
    /* Configure the NVIC Preemption Priority Bits */  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_SetPriority(SysTick_IRQn, 2);

    /*NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);*/

    /* Enable the USART1 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
        
    /* Enable the UART4 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
               
    /* Enable the TIM2 global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;   //抢断优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                     //响应优先级0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                //允许中断
    NVIC_Init(&NVIC_InitStructure);                                                                //写入设置


    /* Enable the TIM3 global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* Enable the TIM4 global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);       

    NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);       

    /* Enable the TIM6 global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;       
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
回复

使用道具 举报

ID:230118 发表于 2020-11-14 11:42 | 显示全部楼层
发现一点细节
出现问题进入tim6中断的前面的情况是,exti0、exti1的中断在大约1ms的时间没有得到执行,而恢复执行时,tim6的1ms定时时间到了,tim6的中断子优先级大于exti1,所以进了tim6的中断函数,但是在tim6的中断函数的断点处看到exti1的中断状态位是1,为什么此前的1ms时间内一直得不到执行呢,它的优先级是0,我想到的只有两种可能,一种是有另一个优先级为0的中断一直占用,一种是发生了系统fault或NMI,后者通过trace信息查看是不存在的,前者只有exti0的中断存在这个可能,但从代码看,exti0中断在中断函数头尾处都有清除,而且其执行时间就1us左右,而硬件测量exti0触发周期有接近10us,而且exti0和exti1是交替触发的,也就是说exti0触发一次后,后续如果exti1没有被触发,那么exti0不会被再次触发,这点从波形图也可以看出来,太奇怪了,大佬们帮忙分析分析

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:230118 发表于 2020-11-14 17:44 | 显示全部楼层
大佬们太忙了,估计是没人指点我了,结帖了,问题凑合解决了,原因只能算是猜测,没有确切证据:
我测试过exti0中断函数执行时间接近2us,exti1大约1us出头,加上进入和退出中断的时间应该在6us以内,理论上频率可以到150k,我在模拟环境上测试就是有漏掉没执行的中断,上机测试,实际频率为10K以内,目前测试4小时以上,无异常,只能理解为频率高了有些中断能检测到边沿,但是进不去中断服务程序,具体原因还没能力分析。
谢谢关注和帮顶的朋友。
回复

使用道具 举报

ID:107913 发表于 2022-1-27 22:48 | 显示全部楼层
楼主,我也想问问,我有个限位器,用的中断关闭步进电机使能,问题是这个有时候能触发中断,有时候又不能触发中断.头都大了
回复

使用道具 举报

ID:1045113 发表于 2022-9-18 17:43 | 显示全部楼层
bro0310 发表于 2020-11-13 18:48
沉了呀,没有大佬指点下我吗,纠正个错误
“当PD8为低电位时,外部电路隔一段时间后会触发EXTI1, 当 ...

现在我也遇到了这种情况,刚开始运行时可以进中断 一段时间后卡死不进中断
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表