• 已解决 73482 个问题
  • 已帮助 5993 位优秀工程师

STM32F103CBT6在运行外部中断时不稳定

33dfa24918ea360d 2018-08-09 浏览量:1949

我在要用到5个独立按键所以就想着用5个外部中断,但是在实际操作中,我发现外部中断不能很好的触发和运行,有时按下按键不能触发,需要多按几次,但是有时候按一下触发好几次,一开始我以为是按键抖动问题,但是加了延时和消抖还是没有什么效果,还有一个就是我触发中断后,等一会它自己就又触发一次,很郁闷。这都是什么情况引起的。我现在程序是用的UCOSII系统,中断也是加在这里面的。我还是按照没有系统写的中断服务程序。




void EXTIX_Init(void)

{
 
   EXTI_InitTypeDef EXTI_InitStructure;
   NVIC_InitTypeDef NVIC_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIOENABLE);//外部中断,需要使能AFIO时钟

 KEY_Init();//初始化按键对应io模式

    //GPIOA.0 中断线以及中断初始化配置
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOAGPIO_PinSource0);

  EXTI_InitStructure.EXTI_Line=EXTI_Line0;
  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.1 中断线以及中断初始化配置
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOAGPIO_PinSource1);

  EXTI_InitStructure.EXTI_Line=EXTI_Line1;
  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.4 中断线以及中断初始化配置
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOAGPIO_PinSource4);

    EXTI_InitStructure.EXTI_Line=EXTI_Line4;
  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寄存器
 
    //GPIOA.4 中断线以及中断初始化配置
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOAGPIO_PinSource5);

    EXTI_InitStructure.EXTI_Line=EXTI_Line5;
  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寄存器 
    
    
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOAGPIO_PinSource6);

    EXTI_InitStructure.EXTI_Line=EXTI_Line6;
  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; //使能按键所在的外部中断通道
  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 = EXTI1_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 = EXTI4_IRQn; //使能按键所在的外部中断通道
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2, 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级1
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
  NVIC_Init(&NVIC_InitStructure); 

    NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //使能按键所在的外部中断通道
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2, 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //子优先级1
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
  NVIC_Init(&NVIC_InitStructure); 
}

 

void EXTI0_IRQHandler(void)

  if(EXTI_GetITStatus(EXTI_Line0)==1)
  {  
    DelayXms(10);
    if(KEY0==0)//判断某个线上的中断是否发生
    PBout(0)=~PBout(0);
  }   
  EXTI_ClearITPendingBit(EXTI_Line0);  //清除EXTI0线路挂起位
}


void EXTI1_IRQHandler(void)

  DelayXms(10);  
  if(KEY1==0)//判断某个线上的中断是否发生
  {
    PBout(6)=~PBout(6);
    PBout(7)=~PBout(7); 
    PBout(8)=~PBout(8);
    PBout(9)=~PBout(9);    
  }      
  EXTI_ClearITPendingBit(EXTI_Line1);  //清除EXTI0线路挂起位
}



void EXTI4_IRQHandler(void)
{
  DelayXms(10);
  while(KEY2==0);
  DelayXms(10);
  if(KEY2==0)//判断某个线上的中断是否发生
  {
    PBout(6)=~PBout(6);
    PBout(7)=~PBout(7); 
    PBout(8)=~PBout(8);
    PBout(9)=~PBout(9);    
  }  
  EXTI_ClearITPendingBit(EXTI_Line4);  //清除EXTI0线路挂起位
}



 void EXTI9_5_IRQHandler(void)
{
  DelayXms(10);
  while(KEY3==0);
  while(KEY4==0);
DelayXms(10);
  
  if(KEY3==0)//判断某个线上的中断是否发生
  PBout(8)=~PBout(8);
  EXTI_ClearITPendingBit(EXTI_Line5); //清除 LINE 上的中断标志位 
  
  if(KEY4==0)//判断某个线上的中断是否发生
   PBout(9)=~PBout(9);
   EXTI_ClearITPendingBit(EXTI_Line6); //清除 LINE 上的中断标志位
}

0 0 收起

我来回答

上传资料:
选择文件 文件大小不超过15M(格式支持:doc、ppt、xls、pdf、zip、rar、txt)
最佳答案
  • 这个问题,我有两个疑问。

    1、你使用了外部中断,不外乎想保证这个信号的最快执行性。但你加了10MS的延时,,我觉得你还不如使用扫描的方式。

        如果你想使用外部中断的方式,我有个建议:
        初始化,打开外部中断,      当中断发生时,在中断函数中关闭信号的中断,并且产生一个信号量。

        在任务中,建一个高优先级的函数,专门处理这个信号量。信号量处理完成,在打开中断。依次循环。

        即使你要按键消抖动,延时也加载主任务中,保证中断函数快进快出。

    2、在中断函数中,需要加入临界段代码保护,及中断的时候不允许系统调度。


    • 发布于 2018-08-09
    • 举报
    • 评论 0
    • 2
    • 0

其他答案 数量:12
  • 你把多个按键用1个中断,使用二极管做个隔离然后对中断上拉,可能你中断开的太多,优先级有冲突
    • 发布于2018-08-09
    • 举报
    • 评论 0
    • 1
    • 0

  • 可能是ucosii的任务优先级问题,还有有可能在强占任务的时候你按下的了按键,导致优先级别错乱
    • 发布于2018-08-09
    • 举报
    • 评论 4
    • 1
    • 0
33dfa24918ea360d 回复了 有人@我 :这个具体怎么解决 回复
33dfa24918ea360d 回复了 有人@我 :优先级不可能要高于系统时钟的优先级 回复
有人@我 回复了 有人@我 :根据运行顺序调整 回复
有人@我 回复了 有人@我 :根据运行顺序调整 回复

  • 有可能是外部信号的问题哦
    • 发布于2018-08-09
    • 举报
    • 评论 0
    • 1
    • 0

33dfa24918ea360d 回复了 afb0b29d219dc0f5 :调度任务是通过定时器中断来执行的 回复
33dfa24918ea360d 回复了 afb0b29d219dc0f5 :调度任务是通过定时器中断来执行的 回复

  • 我估计是你的系统里面把中断关了.系统没有整理好.
    • 发布于2018-08-09
    • 举报
    • 评论 2
    • 0
    • 0
33dfa24918ea360d 回复了 Andrewz :具体在哪里 系统中没有涉及到外部中断 回复
Andrewz 回复了 33dfa24918ea360d :你的ucos系统本身的时钟就会用到中断.进行最基本的任务调度. 回复

  • 你的延时函数是怎样的,放上来看一下

    此外,谨慎在中断里面加延时,会出现一些找不到原因的BUG的

    • 发布于2018-08-09
    • 举报
    • 评论 0
    • 0
    • 0

  • 这个要在你的中断处理函数里面加一个滤波的时间,只要到达时间的电平才去处理按键
    • 发布于2018-08-11
    • 举报
    • 评论 0
    • 0
    • 0

  • 重点排查一下你的延时函数,你的延时函数是阻塞的,最好是用定时器操作
    • 发布于2018-08-17
    • 举报
    • 评论 0
    • 0
    • 0

  • 跟楼上一样,我也怀疑你的延时函数存在问题,你要检查你的延时函数
    • 发布于2018-08-27
    • 举报
    • 评论 0
    • 0
    • 0

  • 延时消抖这个需要在中断响应里面处理,如果是自动触发的话那应该考虑gpio干扰的问题,因为普通的独立按键是不会自动触发的。
    • 发布于2018-08-31
    • 举报
    • 评论 0
    • 0
    • 0

  • 那是因为你的按键的外部中断优先级太低了   UCOS是根据优先级来玩的  你的按键优先级低,就会一直被搁置
    • 发布于2018-09-09
    • 举报
    • 评论 0
    • 0
    • 0

相关问题

问题达人换一批

STM32F103CBT6在运行外部中断时不稳定