ajleo 发表于 2018-10-13 17:24:29

stm32外中断多次触发

请问各位大佬一个外中断异常多次触发的问题
void EXTI4_IRQHandler()
{
static int x = 0;
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0)//判断按键是否按下
{                                                                                                      
EXTI_ClearITPendingBit(EXTI_Line4);
x++;
GPIO_SetBits(GPIOF,GPIO_Pin_8);//设置蜂鸣器发声
delay_ms(200);
GPIO_ResetBits(GPIOF,GPIO_Pin_8);
if(x > 1)
{
   x = 0;
   GPIO_ResetBits(GPIOF,GPIO_Pin_9);//控制灯闪烁
   delay_ms(200);
}
GPIO_SetBits(GPIOF,GPIO_Pin_9);
}
}
可是把if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0)//判断按键是否按下
换成
if(EXTI_GetITStatus(EXTI_Line4)!=RESET)//判断某个线上的中断是否发生
就会判断出不定时触发了两次,当按键设置成下降沿触发时
EXTI_InitStruct.EXTI_Line = EXTI_Line4;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStruct);

小耳朵1500922649 发表于 2018-10-13 17:46:59

中断耗时太久啦,不要再中断里delay

ajleo 发表于 2018-10-13 18:50:33

小耳朵1500922649 发表于 2018-10-13 17:46
中断耗时太久啦,不要再中断里delay

改了,不是延时的问题

wenyangzeng 发表于 2018-10-13 19:31:14

1、中断函数里放入延时尤其是SysTick延时很容易出现预料不到的冲突的。
2、楼主在进入中断函数后并未立即清中断标志位,而是先来给10ms延时,你可知道在这延时期间按键的抖动已经又触发了多少次外部中断了?

ajleo 发表于 2018-10-13 19:38:46

wenyangzeng 发表于 2018-10-13 19:31
1、中断函数里放入延时尤其是SysTick延时很容易出现预料不到的冲突的。
2、楼主在进入中断函数后并未立即清 ...

那按键检测的最佳写法应是怎样?还请大佬们明示

wenyangzeng 发表于 2018-10-13 22:05:55

ajleo 发表于 2018-10-13 19:38
那按键检测的最佳写法应是怎样?还请大佬们明示

1、清中断标志位
2、禁止EXTI中断
3、点亮LED
4、使能EXTI中断

熄灭LED放在定时中断里执行。

tyq123ui 发表于 2018-10-14 16:00:20

我也是有点懵逼了

ajleo 发表于 2018-10-14 17:18:16

wenyangzeng 发表于 2018-10-13 22:05
1、清中断标志位
2、禁止EXTI中断
3、点亮LED


谢谢大佬,也就是说中断里只放标志位了

toofree 发表于 2018-10-14 21:21:55

本帖最后由 toofree 于 2018-10-14 21:37 编辑

检测按键,可以用定时扫描的方法。
给你个鼠标按键按下、弹起,上下双沿检测程序,单次响应,逻辑稍微复杂一点。一般用的都比这简单。
typedef struct
{
    unsigned LDOWN:6;
    unsigned LDEN   :1;
    unsigned LDOWN7 :1;
    unsigned LUP    :6;
    unsigned LUEN   :1;
    unsigned LUP7   :1;
    unsigned RDOWN:6;
    unsigned RDEN   :1;
    unsigned RDOWN7 :1;
    unsigned RUP    :6;
    unsigned RUEN   :1;
    unsigned RUP7   :1;
}Mouse_Key;

extern Mouse_Key MsKey;void Button_Process(void)
{
    if(BUTTON_IsPressed(PS2_BUTTON_LEFT) == true)
    {
      LED_On(LED_D3);
      if (MsKey.LDEN == 1)
      {
            if (MsKey.LDOWN >= 5)
            {
                MsKey.LDOWN7 = 1;
                MsKey.LDEN = 0;
                MsKey.LUEN = 1;
            }
            else
            {
                MsKey.LDOWN++;
            }
      }

      MsKey.LUP = 0;
    }
    else
    {
      LED_Off(LED_D3);
      MsKey.LDOWN = 0;

      if (MsKey.LUEN == 1)
      {
            if (MsKey.LUP >= 5)
            {
                MsKey.LUP7 = 1;
                MsKey.LUEN = 0;
                MsKey.LDEN = 1;
            }
            else
            {
                MsKey.LUP++;
            }
      }
    }
    if(BUTTON_IsPressed(PS2_BUTTON_RIGHT) == true)
    {
      LED_On(LED_D4);
      if (MsKey.RDEN == 1)
      {
            if (MsKey.RDOWN >= 5)
            {
                MsKey.RDOWN7 = 1;
                MsKey.RDEN = 0;
                MsKey.RUEN = 1;
            }
            else
            {
                MsKey.RDOWN++;
            }
      }

      MsKey.RUP = 0;
    }
    else
    {
      LED_Off(LED_D4);
      MsKey.RDOWN = 0;

      if (MsKey.RUEN == 1)
      {
            if (MsKey.RUP >= 5)
            {
                MsKey.RUP7 = 1;
                MsKey.RUEN = 0;
                MsKey.RDEN = 1;
            }
            else
            {
                MsKey.RUP++;
            }
      }
    }
}
MsKey.LDOWN7,MsKey.LUP7,MsKey.RDOWN7, MsKey.RUP7,4个标志位在主程序中处理完才清除。


feixiang20 发表于 2018-10-14 22:48:52

中断里放标志位只能暂时看看作用,有时硬件冲突和浮空模式IO灵敏过头也会引起无常中断的
页: [1]
查看完整版本: stm32外中断多次触发