Arduino 触摸按键:实现单击,双击,长按功能,稳定无抖动。

实现思路:
由具体多次测试可得出不同的按键状态条件如下:

  1. 单击
    ① 产生一个下降沿(高电平 -> 低电平)
    ② 150ms 内没有再产生下降沿
  2. 双击
    ① 产生第一个下降沿(高电平 -> 低电平)
    ② 产生第二个下降沿:两个下降沿的间隔需要在150ms内,判断为双击,反之判断为单击。
  3. 长按
    ① 高电平持续时间 >700ms

要点:
双击判断时,第一次按下后,要及时设置标志位,排除单击情况并更新状态,反之立刻判断为单击更新按键状态。

Tips:
不同的实物按键可能具有不同的参数: 单击可产生(上升沿/下降沿)、两次跳变沿的间隔时间不同等等。

可自己根据你们的实际测试的按键参数进行参数修改

#ifndef TOUCH_H
#define TOUCH_H

#define TOUCH_PWR           32
#define TOUCH_PIN           15

enum
{
  None,
  ONE,
  DOUBLE,
  LONG,
};

u32 RisTime = 0;
u32 FalTime = 0;
u32 firstTouchTime = 0;
bool isDouble = 0;
bool isOne = 0;
int touchStatus = 0;

#endif
void Touch_init()
{
  /*Set touch Pin as input*/
  pinMode(TOUCH_PIN, INPUT);
  pinMode(TOUCH_PWR, PULLUP);
  digitalWrite(TOUCH_PWR, HIGH);
  attachInterrupt(digitalPinToInterrupt(TOUCH_PIN), TouchRising_ISR, RISING);
}

void TouchRising_ISR()
{
  if (isOne && millis() - firstTouchTime <= 150)
  {
    isOne = 0;
    isDouble = 1;
    touchStatus = 2;
    Serial.print("touchStatus:");
    Serial.println(touchStatus);
  }

  RisTime = millis();
  attachInterrupt(digitalPinToInterrupt(TOUCH_PIN), TouchFalling_ISR, FALLING);
}

void TouchFalling_ISR()
{
  u32 highLastTime = 0;
  FalTime = millis();
  highLastTime = FalTime - RisTime;
  
  if ( highLastTime > 700)
  {
    touchStatus = 3;
  }
  else if (isDouble)
  {
    isDouble = 0;
  }
  else
  {
    isOne = 1;
    firstTouchTime = millis();
  }
  attachInterrupt(digitalPinToInterrupt(TOUCH_PIN), TouchRising_ISR, RISING);
}

int Get_TouchStatus()
{
  static u32 timeStatus = 0;
  //10ms 执行一次按键扫描
  if (MyTimingisOk(&timeStatus, 10))
  {

    if (isOne && millis() - firstTouchTime > 150)
    {
      isDouble = 0;
      isOne = 0;
      touchStatus = 1;
    }

    switch (touchStatus)
    {
      case None:   /*按键无点击情况*/   break;
      case ONE:    /*按键单击情况*/     break;
      case DOUBLE: /*按键双击情况*/     break;
      case LONG:   /*按键长按情况*/     break;
    }
    touchStatus = 0;
  }
}



bool MyTimingisOk(u32* lastTime,u16 setTime)
{
  if(millis()-*lastTime>setTime)
  {
    *lastTime=millis();
    return true;
  }
  return false;
}

主循环中,10ms进行一次按键扫描(状态判定)

void setup() {
  Serial.begin(115200);
  Touch_init();
}

void loop()
{
  Get_TouchStatus();
}

你可能感兴趣的:(Arduino,arduino)