第4章键盘检测原理及应用实现
键盘分为编码键盘和非编码键盘。键盘上闭合键的识别由专用的硬件编码器实现,并产 生键编码号或键值的称为编码键盘,如计算机键盘。而靠软件编程来识别的键盘称为非编码 键盘,在单片机组成的各种系统中,用的较多的是非编码键盘。非编码键盘又分为独立键盘 和行列式(又称矩阵式)键盘。
4.1独立键盘检测
键盘实际上就是一组按键,在单片机外围电路中,通常用到的按键都是机械弹性开关, 当幵关闭合时,线路导通,开关断开时,线路断开,图4.1.1是几种单片机系统常见的按键。
弹性小按键被按下时闭合,松手后自动断开;自锁式按键按下时闭合且会自动锁住,只 有再次按下时才弹起断开。通常我们把自锁试按键当做开关使用,比如TX-1C实验板上的电 源幵关就使用自锁按键。单片机的外围输入控制用小弹性按键较好,单片机检测按键的原理 是:单片机的I/O 口既可作为输出也可作为输入使用,当检测按键时用的是它的输入功能, 我们把按键的一端接地,另一端与单片机的某个I/O 口相连,开始时先给该I/O 口赋一高电平, 然后让单片机不断地检测该I/O 口是否变为低电平,当按键闭合时,即相当于该I/O 口通过按 键与地相连,变成低电平,程序一旦检测到I/O 口变为低电平则说明按键被按下,然后执行 相应的指令。
按键的连接方法非常简单,如图4.1.2所示,右侧I/O端与单片机的任一 I/O 口相连。按 键在被按下时,其触点电压变化过程如图4.1.3所示。
从图4.1.3可看出,理想波形与实际波形之间是有区别的,实际波形在按下和释放的瞬间 都有抖动现象,抖动时间的长短和按键的机械特性有关,一般为5?10ms。通常我们手动按 下键然后立即释放,这个动作中稳定闭合的时间超过20ms。因此单片机在检测键盘是否按下 时都要加上去抖动操作,有专用的去抖动电路,也有专用的去抖动芯片,但通常我们用软件 延时的方法就能很容易解决抖动问题,而没有必要再添加多余的硬件电路。
用示波器跟踪不同类型的开关,得到图4.1.4和图4.1.5的波形,观察波形可以帮助我们 对抖动现象有一个直观的了解。图4.1.4是一个小的按钮开关在闭合时的抖动现象,水平轴 2ms/Div,抖动间隙大约为10ms,在达到稳定状态前一共有6次变化,频率随时间升高。
图4.1.5是一个小型继电器在闭合时的抖动现象,水平轴2ms/Div,抖动间隙大约为8ms, 在达到稳定状态前一共有13次变化。注意在开始和结束时,几个小的脉冲后伴随较高的频率。
编写单片机的键盘检测程序时,一般在检测按下时加入去抖延时,检测松手时就不用加 了。按键检测流程图如图4.1.6所不。
TX-1C实验板上独立键盘与单片机连接原理图如图4.1.7所示。
实验板上键盘区最下面一行S2?S5为4个独立键盘,与单片机的P3.4?P3.7分别相连, 如图4.1.8所示。
下面通过一个实例来讲解独立键盘的具体操作方法,在TX-1C实验板上实现如下描述。 【例4.1.1】用数码管的前两位显示一个十进制数,变化范围为00?59,开始时显示00, 每按下S2键一次,数值加1;每按下S3键一次,数值减1;每按下S4键一次,数值归零; 按下S5键一次,利用定时器功能使数值开始自动每秒加1,再次按下S5键,数值停止自动 加1,保持显示原数。新建文件part2.2_l.c,程序代码如下:
#include
void display(uchar numdis) //显示子函数 { uchar shi,ge; //分离两个分别要显示的数 shi=numdis/10; ge=numdis;
dula=1; P0=table[shi]; //送十位段选数据 dula=0; P0=0xff; //送位选数据前关闭所有显示,防止打开位选锁存时 wela=1; //原来段选数据通过位选锁存器造成混乱
P0=0xfe; //送位选数据 wela=0; delayms(5); //延时 dula=1; P0=table[ge]; //送个位段选数据 dula=0; P0=0xff; wela=1; P0=0xfd; wela=0; delayms(5); }
void delayms(uint xms) { uint i,j; for(i=xms;i>0;i--) //i=xms即延时约xms毫秒 for(j=110;j>0;j--); }
void init() //初始化函数 { TMOD=0x01;//设置定时器0为工作方式1(0000 0001) TH0=(65536-45872)/256;//装初值50ms一次中断 TL0=(65536-45872)%6; EA=1; //开总中断 ET0=1; //开定时器0中断 }
void keyscan() { if(key1==0) { delayms(10); if(key1==0) { num++; if(num==60)//当到60时重新归0 num=0; while(!key1);//等待按键释放 } } if(key2==0) { delayms(10); if(key2==0)