目录

1.传统机械按键抖动原理

1.1波形图

2.不做消抖处理(建议实际操作一遍)

  2.1连线图:

2.2代码:(可以按键测试,如果不加消抖,计数会跳变)

3.简单的延时消抖 (阻塞消抖)

3.1连线与2.1一样.

3.2代码:(可以实际烧录测试一下效果,千看万看不如经手一遍)

4.定时器消抖

4.1定时器消抖原理

4.2逻辑代码

4.3定时器消抖整体代码 

5.硬件消抖(一般不用,处于体积和成本的考虑)

 5.1 RS触发器消抖:

5.2 电容消抖

双击,三连击讲解和代码入口:


1.传统机械按键抖动原理

        机械按键的工作原理是通过物理触点接触来完成信号的传递。当按下一个机械按键时,按键内部的金属片(或弹簧)会接触到电路板上的触点。这种接触往往并非瞬时稳定,而是会经历一段微小的震动过程,称为“触点抖动”或“开关抖动”。也就是说机械按键抖动是不可避免的,我们要做的是消去这个抖动,让它的影响最小。一般为5-20ms(具体时间不做计较,实际应用延迟消抖并不好用,后文我们统一按延时15ms去处理),实际上的波形:(因机械结构出现的无可避免的抖动)只需要在按下前置的时候加入延时(A段前置抖动  B段后置抖动)

1.1波形图

图1

这些抖动就干扰了我们单读读取引脚为低电平时的判断,产生错误结果。

2.不做消抖处理(建议实际操作一遍)

  2.1连线图:

2.2代码:(可以按键测试,如果不加消抖,计数会跳变)

int a=0;
void setup() {
  pinMode(2, INPUT_PULLUP);//按键上拉,按键一端连接GND 一端连接引脚2
  Serial.begin(115200);
}
void loop() {
  if (digitalRead(2) == LOW)  //读取按键是否为低电平,也就是按键是否按下
  {
    if (digitalRead(2) == LOW)
    {
      a++;
      Serial.println(a);
      while (digitalRead(2) == LOW);//松手检测
    }
  }
}

3.简单的延时消抖 (阻塞消抖)

3.1连线与2.1一样.

在检测到第一个低电平的瞬间延时10ms,跳过A段抖动.

3.2代码:(可以实际烧录测试一下效果,千看万看不如经手一遍)

int a=0;//计数标志位
void setup() {
  pinMode(2, INPUT_PULLUP);//按键上拉,按键一端连接GND 一端连接引脚2
  Serial.begin(115200);
}
void loop() {
  if (digitalRead(2) == LOW) //读取按键是否为低电平,也就是按键是否按下
  {
    delay(15); //增加的延时,为阻塞延时,在arduino系列介绍过阻塞延迟的坏处
    if (digitalRead(2) == LOW)
    {
      a++;
      Serial.println(a);
      while (digitalRead(2) == LOW);//松手检测
    }
  }
}

4.定时器消抖

4.1定时器消抖原理

        用定时器中断每隔15ms检测一次按键状态.记上次按键的状态为 pre_state 当前按键状态为 now_state,用digitalRead(key);来读取按键的电平.并赋值给now_state.

按键按下:上次电平是1,当前电平是0.

按键松手:上次电平是0,当前电平是1.

        即使在抖动区间,如果检测到0视为按下,如果检测到1,等下一个15ms肯定会检测到状态是0,用这种思路,可实现消抖处理.

4.2逻辑代码

        我将逻辑代码放置在的loop中,我们尽可能的避免在中断里执行函数.只做简单赋值,先看看里面代码学习思维,文章后面附全部代码.

volatile int flag=0;
static int pre_state=1,now_state=1;
  if(flag==1)//flag为15ms的中断标志位
  {
      pre_state=now_state;//记录上次now_state赋值给pre_state
      now_state=digitalRead(2);
      if(pre_state==1&&now_state==0)
      {
          Serial.println("按键按下");
      }
      if(pre_state==0&&now_state==1)
      {
          Serial.println("按键松开");
      }
      flag=0;
  }

4.3定时器消抖整体代码 

      按键松开和按下都会让m++,下述代码可以看到程序正在不断运行,哪怕你按下按键也不会阻断程序.哪怕你快速敲击按键也不会有影响.建议下载到自己开发板上测试效果.

#include <TimerOne.h>

volatile int flag=0,count=0;
void setup(void)
{
  pinMode(2, INPUT_PULLUP);//按键上拉输入
  Timer1.initialize(1000);//精确度1ms 
  Timer1.attachInterrupt(Interrupt_callback); // 定时器的中断回调函数
  Serial.begin(115200);
}
void Interrupt_callback(void)//定时器中断函数内我没有执行函数,只进行标志位的更新,让主程序轮询捕捉15ms的计时
{
  if(flag==0)
  {
    count++;
    if(count>15)
    {
      count=0;
      flag=1;
    }
  }
}
void loop(void)
{
  static int m=0;//按键松开和按下都会让m++
  Serial.println(m);
  static int pre_state=1,now_state=1,Key_state=0;
  if(flag==1)//flag为15ms的中断标志位
  {
      pre_state=now_state;//记录上次的电平
      now_state=digitalRead(2);
      if(pre_state==1&&now_state==0)
      {
          Serial.println("按键按下");
          m++;
      }
      if(pre_state==0&&now_state==1)//一般来说只用按键松开,可以将上边的if判断删除,我留下的目的是如果有特殊需求也方便直接使用
      {
          Serial.println("按键松开");
          m++;
      }
      flag=0;
  }
}

5.硬件消抖(一般不用,处于体积和成本的考虑)

 5.1 RS触发器消抖:

        RS触发器利用其特性来吸收按键的抖动。当按键被按下时,触发器会立即翻转状态,而按键的抖动不会影响输出,因为触发器的状态改变是瞬间的,不受后续抖动的影响。

5.2 电容消抖

        电容滤波器通过并联一个电容器在按键两端,利用电容的充放电特性来消除抖动。当按键产生抖动时,电容器会吸收这些快速变化的电平,从而减少抖动对电路的影响。

并联一个0.1uf的电容进行消抖处理.

双击,三连击讲解和代码入口:

arduino按键由浅入深,消抖(阻塞消抖,定时器消抖),单击,双击,三连击全部掌握(二)-CSDN博客

更多推荐