独立按键_单片机_普中
1 独立按键的介绍
键盘分为编码键盘和非编码键盘。键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或键值的称为编码键盘,如计算机键盘。而靠软件编程来识别的键盘称为非编码键盘,在单片机组成的各种系统中,用的较多的是非编码键盘。非编码键盘又分为独立键盘和行列式键盘(常说的矩阵键盘)。
单片机的IO口既可作为输出也可作为输入使用,当检测按键时用的是它的输入功能,我们把按键的一端接地,另一端与单片机的某个I/O口相连,开始时先给该IO口赋一高电平,然后让单片机不断地检测该I/O口是杏变为低电平,当按键闭合时,即相当于该I/O口通过按键与地相连,变成低电平,程序一旦检测到I/O口变为低电平则说明按键被按下,然后执行相应的指令。
注:自锁开关:是一种常见的按钮开关。在开关按钮第一次按时,开关接通并保持,即自锁,在开关按钮第二次按时,开关断开,同时按钮弹出来。
2 机械按键的原理
由于机械触点的弹性作用,一个按键开关在闭合时不会马上就稳定的接通,在断开时也不会一下子彻底断开,而是在闭合和断开的瞬间伴随了一连串的抖动。由于单片机检测 IO口速度非常快,超过弹片抖动的频率,所以在检测按键状态时,要消除按键抖动的影响。一般认为,抖动不超过10ms。
为了避免这种现象而做的措施就是按键消抖,消抖方法分为:硬件消抖和软件消抖。
(1)硬件消抖
在按键上并联一个电容(RC电路),利用电容的充放电特性来对抖动过程中产生的电压毛刺进行平滑处理,从而实现消抖。
(2)软件消抖
当检测到按键状态变化后,先等待一个 10ms 左右的延时时间,让抖动消失后再进行一次按键状态检测,如果与刚才检测到的状态相同,就可以确认按键已经稳定的动作了。
判断按键一次按下的具体方法:
a)检查到按键按下后,进行10-15ms延时,用于跳过这个抖动区域;
b)延时后再监测按键状态,如果没有按下表明是抖动或者干扰造成,如果仍旧按下,可以认为是真正的按下。并进行对应的操作。
3)同样按键释放后也要进行去抖动延时,延时后监测按键是否真正松开。
3 功能要求:通过开发板上的独立按键K1-K4分别控制LED1-LED4指示灯亮灭。
4 硬件设计
5 软件设计
1 #include "reg52.h" 2 3 typedef unsigned char u8; 4 typedef unsigned int u16; 5 6 //定义独立按键控制管脚,输入信号 7 sbit KEY1 = P3^1; 8 sbit KEY2 = P3^0; 9 sbit KEY3 = P3^2; 10 sbit KEY4 = P3^3; 11 12 //定义LED控制管脚,输出信号 13 sbit LED1 = P2^0; 14 sbit LED2 = P2^1; 15 sbit LED3 = P2^2; 16 sbit LED4 = P2^3; 17 18 //使用宏定义独立按键按下的键值,区别哪一个按键 19 #define KEY1_PRESS 1 20 #define KEY2_PRESS 2 21 #define KEY3_PRESS 3 22 #define KEY4_PRESS 4 23 #define KEY_UNPRESS 0 24 25 //延时函数,当ten_us=1时,大约延时10us 26 void delay_10us(u16 ten_us) 27 { 28 while(ten_us--); 29 } 30 31 //按键监测函数,用来监测四个按键中哪一个按键按下,它会返回一个值 32 u8 key_scan(u8 mode) 33 { 34 static u8 key = 1; //静态变量,可以保持上一次的值 35 36 if(mode) key = 1; //mode=1,连续扫描按键(长按);mode=1, 单次扫描按键(短按) 37 38 if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0)) //任意按键按下 39 { 40 delay_10us(1000); //延迟10ns,滤除按下抖动过程 41 key = 0; 42 if(KEY1 == 0) 43 return KEY1_PRESS; //消抖后,再次监测到KEY1按下,返回按键1的码值 44 else if(KEY2 == 0) 45 return KEY2_PRESS; 46 else if(KEY3 == 0) 47 return KEY3_PRESS; 48 else if(KEY4 == 0) 49 return KEY4_PRESS; 50 } 51 else if(KEY1==1 && KEY2==1 && KEY3==1 && KEY4==1) //没有按键按下,同时都为高电平 52 { 53 key = 1; //为按键下次操作 54 } 55 return KEY_UNPRESS; 56 } 57 58 void main() 59 { 60 u8 key_value = 0; 61 62 while(1) 63 { 64 key_value = key_scan(0); 65 66 if(key_value == KEY1_PRESS) //监测到KEY1按下,控制LED1状态翻转 67 LED1 = !LED1; 68 else if(key_value == KEY2_PRESS) 69 LED2 = !LED2; 70 else if(key_value == KEY3_PRESS) 71 LED3 = !LED3; 72 else if(key_value == KEY4_PRESS) 73 LED4 = !LED4; 74 } 75 }
6 实验现象
使用USB线将开发板和电脑连接成功后(电脑能识别开发板上CH340串口),把编译后产生的.HEX文件烧入芯片内,现象如下:当按下K1键,LED1指示灯亮;再按下K1键,LED1指示灯灭,如此循环。
7 其他
独立按键的四大要素:
“自锁”:按键一旦进入到低电平,就要“自锁”起来,避免不断触发按键,只有当按键被松开变成高电平的时候,才及时“解锁”为下一次触发做准备。
“消抖”:按键是一个机械触点器件,在接触的瞬间必然存在微观上的机械抖动,反馈到电平的瞬间就是“高,低,高,低…”这种不稳定的电平状态是一种干扰,但是,按键一旦按下去稳定了之后,这种状态就消失,电平就一直保持稳定的低电平。消抖的本质就是滤波,要把这种接触的瞬间抖动过滤掉,避免按键的“一按多触发”。
“非阻塞”:在处理消抖的时候,必须用到延时,如果此时用阻塞的delay延时就会影响其它任务的运行效率,因此,用非阻塞的定时延时更加有优越性。
“清零式滤波”:在消抖的时候,有两种境界,第一种境界是判断两次电平的状态,中间插入“固定的时间”延时,这种方法前后一共判断了两次,第一次是识别到低电平就进入延时的状态,第二次是延时后再确认一次是否继续是低电平的状态,这种方法的不足是,“固定的时间”全凭经验值,但是不同的按键它们的抖动时间长度是不同的,除此之外,前后才判断了两次,在软件的抗干扰能力上也弱了很多,“密码等级”不够高。第二种境界就是“清零式滤波”,“清零式滤波”非常巧妙,抗扰能力超强,它能自动过滤不同按键的“抖动时间”,然后再进入一个“稳定时间”的“N次识别判断”,更加巧妙的是,在“抖动时间”和“稳定时间”两者时间内,只要发现一次是高电平的干扰,就马上自动清零计时器,重新开始计时。“稳定时间”一般取20ms到30ms之间,而“抖动时间”是隐藏的,在代码上并没有直接描写出来,但是却无形地融入了代码之中,只有慢慢体会才能发现它的存在。
8 参考资料