本人第一次发帖,如果有错误,欢迎大家指正!!!有关按键消抖的话题已经有很多人提出来了,在这里我把它进行一个总结。希望能帮助到大家!
1.按键抖动的原因
按键消抖通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。形成以下的波形
2.按键抖动的原理
按键抖动时间的长短由按键的机械特性决定,一般为5ms~10ms。这是一个很重要的时间参数,在很多场合都要用到。按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。键抖动会引起一次按键被误读多次。为确保单片机对按键的一次闭合仅作一次处理,必须去除键抖动。在键闭合稳定时读取键的状态,并且必须判别到按键释放到稳定状态后再去作处理。
3.按键消抖的方法
(1)硬件的消抖
利用电容的充放电特性来对抖动过程中产生的电压毛刺进行平滑处理,从而实现消抖。在按键的两端并联一个0.1uf的电容。如按键消抖硬件图
。
(2)软件的消抖
1.延时消抖
刚接触单片机的时候,最常用的方法,利用延时,消去抖动。代码如下:
if(按键是否按下)
{ //按键按下的条件下
Deadly_1ms(5); // 延时消去抖动
if(按键是否按下)
{ //按键再次确认按下
//执行按键功能
while(按键是否松开);
}
}
注:按键详细代码见工程文件延时消抖
2.状态机消抖
将按键的状态分为三种 是否按下,是否抖动,是否弹起。检测到按下时,转向判断是否抖动,并执行按键功能。等按键功能执行完了以后直接跳到按键是否弹起的状态。等弹起后,再来判断是否按下的状态。
在按键的原理图中,将1、2相接,则构成的是4*4的矩阵键盘,并且矩阵键盘与单片机的P3口相接。
//按键原理图见上传的图片
//设置按键的三种状态及按键接口
#define KEY P3
#define key_state_0 0 //判断是否按下
#define key_state_1 1 //判断是否为抖动
#define key_state_2 2 //判断是否弹起
unsigned char key_read(void)
{
static char key_state = key_state_0;
unsigned char key_return=0, key_press;
unsigned char key1,key2;
KEY=0xf0;
key1=KEY&0xf0;
KEY=0x0f;
key2=KEY&0x0f;
key_press =key1|key2; //读取矩阵按键每个按键的状态,存在key_press里
switch (key_state) // 判断按键状态
{
case key_state_0: //是否按下
if (key_press!=0xff) key_state = key_state_1; //没有按键按下时则读取出的0xff,若有不同说明有按键按下,则跳转到判断是否为抖动的状态
break;
case key_state_1:
if (key_press !=0xff) //再次确认是否按下,防止因单片机的速度过快,导致误判。
{
switch (key_press)//根据key_press的值来执行相对应的功能
{
case 0xee: key_return = 19; //这里的0xee是怎么的来的,简单来推一下
case 0xed: key_return = 18; //单片机的P3口初始化输出的是高电平,先将P3口输出0xf0,如果有按键按下,则P3口中的高四位的某一位的电平会被拉低,此时记录P3口的状态(key1)
case 0xeb: key_return = 17; //读取了高四位的电平,之后再来读取低四位的电平(key2) ,之后 | 在一起得到key_press,得到的key_press中一定有两位是0;
case 0xe7: key_return = 16;//举例 : 当我按下s19时,key1 = 0xe0;(即P3^4 = 0,高四位的第一位电平被拉低),key2 = 0x0e;(即P3^0 = 0,低四位的第一位电平被拉低),这样key_press = key_press =key1|key2 = 0xee;
case 0xde: key_return = 15;//以此类推
case 0xdd: key_return = 14;
case 0xdb: key_return = 13;
case 0xd7: key_return = 12;
case 0xbe: key_return = 11;
case 0xbd: key_return = 10;
case 0xbb: key_return = 9;
case 0xb7: key_return = 8;
case 0x7e: key_return = 7;
case 0x7d: key_return = 6;
case 0x7b: key_return = 5;
case 0x77: key_return = 4;
}
key_state = key_state_2; //这里跳转到判断弹起的状态
}
else
key_state = key_state_0;
break;
case key_state_2:
if (key_press==0xff) key_state = key_state_0; //等待按键完全弹起
break;
}
return key_return;
}
注:具体用法见工程状态机消抖
3.逻辑关系消抖
将按键的原理图中,将2、3相接,则构成的是独立键盘(s4,s5,s6,s7),并且独立键盘与单片机的P3口的低四位相接,另一端与gnd相接。
利用逻辑关系 与&、或 | 、非 !、异或 ^,来消除抖动。先贴出源代码:
unsigned char ReadData = KEYPORT^0xff;
Trg = ReadData & (ReadData ^ Cont);
Cont = ReadData;
Trg是判断那个按键按下,Cont用来判断长按、短按的;
分析: (1)没有按键按下(初始值 Trg = 0,Cont = 0)
unsigned char ReadData = P3^0xff; => ReadData = 0xff ^0xff = 0x00;
Trg = ReadData & (ReadData ^ Cont); =>Trg =0x00 & (0x00 ^0x00) = 0x00;
Cont = ReadData; =>Cont = 0x00;
结果 :
ReadData = 0x00
Trg = 0x00
Cont = 0x00
(2) s4按下
刚按下时
unsigned char ReadData = P3^0xff; => ReadData = 0xf7 ^0xff = 0x08;
Trg = ReadData & (ReadData ^ Cont); =>Trg =0x08 & (0x08^0x00) = 0x08;
Cont = ReadData; =>Cont = 0x08;
抖动时
unsigned char ReadData = P3^0xff; => ReadData = 0xff ^0xff = 0x00;
Trg = ReadData & (ReadData ^ Cont); =>Trg =0x00 & (0x00^0x08) = 0x00;
Cont = ReadData; =>Cont = 0x00;
结果 :
刚按下时:
ReadData = 0x08
Trg = 0x08
Cont = 0x08
抖动时:
ReadData = 0x00
Trg = 0x00
Cont = 0x00
(3) s4长按
unsigned char ReadData = P3^0xff; => ReadData = 0xf7 ^0xff = 0x08;
Trg = ReadData & (ReadData ^ Cont); =>Trg =0x08 & (0x08 ^0x00) = 0x00;
Cont = ReadData; =>Cont = 0x08;
结果 :
ReadData = 0x08
Trg = 0x00
Cont = 0x08
(4) s4松开
unsigned char ReadData = P3^0xff; => ReadData = 0xff ^0xff = 0x00;
Trg = ReadData & (ReadData ^ Cont); =>Trg =0x08 & (0x08 ^0x00) = 0x00;
Cont = ReadData; =>Cont = 0x00;
结果 :
ReadData = 0x00
Trg = 0x00
Cont = 0x00
将上面的数据进行汇总、分析 | ReadData | Trg | Cont | 没有按键按下 | 0x00 | 0x00 | 0x00 | s4刚按下 | 0x08 | 0x08 | 0x08 | s4有抖动时 | 0x00 | 0x00 | 0x00 | s4长按 | 0x08 | 0x00 | 0x08 | s4松开 | 0x00 | 0x00 | 0x00 |
Trg只有在按键刚按下时有不到等于0的值,因此我们检测到Trg 不为0时,说明有按键按下;
Cont 只要有按键按下时,它的值就不为0,因此我们定时一段时间,来检测Cont,,若不变,则按键时长按的状态。
注:具体用法见工程逻辑关系消抖
到这里只是简单的介绍了几种按键消抖,还有很多方法没有介绍,比如,中断消抖,门电路消抖,计时消抖…,但万变不离其中。学会了其中一种,其他的就自然懂了。
希望这篇帖子能帮助到大家!!!!
全部资料51hei下载地址(全部程序源码):
按键.rar
(68.28 KB, 下载次数: 171)
|