目录
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波形图
这些抖动就干扰了我们单读读取引脚为低电平时的判断,产生错误结果。
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
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博客