键盘工作原理1.按键输入的特点键盘实质上是一组按键开关的组合。通常使用的是触点式的机械弹性开关。利用机械触点的通断,实现按下时开关导通,释放时开关断开的功能。按键触点的一端和单片机的I/O端口引脚连接,另一端与电压信号相连,触点的通断即可引起端口引脚上的电压变化,单片机通过程序读入I/O端口引脚电平信号便可判断按键的状态。如下图所示。当按键未按下压时,Px.n端口为高电平;按压按键后为低电平。按键在闭合和断开时,触点会存在抖动现象:按下抖动释放抖动理想波形实际波形稳定闭合+5V+5VAB无抖动有抖动图为键闭合时列线电压波形。键闭合和断开过程中存在抖动期(呈现一串负脉冲),抖动时间长短与开关的机械特性有关,一般为5~10 ms之间;稳定闭合期由操作员的按键动作所确定,一般为数百毫秒到几秒。为了保证CPU对键的闭合做一次处理,必须去除抖动,在键的稳定闭合或断开时,读键的状态。软件消抖方法:当判别到键盘上有键闭合后,延时一段时间再判别键盘的状态,若仍有键闭合,则认为键盘上有一个键处于稳定的闭合状态,否则认为键抖动。按下抖动释放抖动理想波形实际波形稳定闭合+5V+5VAB无抖动有抖动键盘有两种结构:独立式按键和矩阵式按键。1.独立式按键独立式键盘中每个按键都单独连接到单片机的一个I/O端口引脚上。特点是电路简单,但占用I/O口线较多。例:按下按键,对应的LED灯亮#includereg51.hvoiddelay(unsignedintz){unsignedintx,y;for(x=z;x0;x--)for(y=125;y0;y--);}voidmain(){unsignedcharkey;P2=0x00;P0=0x01;while(1){key=P0;if(key!=0x01){delay(10);if(key!=0x01)P2=~key;}}}实例独立按键识别【要求】采用独立按键方式实现下述功能:开机时LED全熄,然后根据按键动作使相应灯亮,并将亮灯保持到按压其它键时为止。做输入,先写1①按键的闭合电平为0,但LED的驱动电平为1,故不能直接将P0口的状态送到P2口,而应使其先取反再送出;②使按键按下LED点亮,松开时保持不变。【分析】#includereg51.hvoiddelay(unsignedintz){unsignedintx,y;for(x=z;x0;x--)for(y=125;y0;y--);}voidmain(){unsignedcharkey;P2=0x00;P0=0x0f;while(1){key=P0;if(key!=0x0f){delay(10);if(key!=0x0f)P2=~key;}}}实例键控流水灯【要求】K1为“启动键”,按压K1可产生“自下向上”的流水灯运动;K2为“方向键”,按压K2可产生“自下向上”运动。启动停止run(=1)(=0)↓↑dir(=1)(=0)获取按下键值(键值函数)流程键值:按压K1——xxxxxx10(0x02)按压K2——xxxxxx01(0x01)无按键——0000xx11(0x03)按键动作判断——(P0&0x03)是否等于0x03若是,则无按键动作,反之则有按键动作则由得到的键值对应确定dun、dir的值,用switch语句实现。temp=P0&0x03;switch(temp){case0x02:run=1;dir=1;break;case0x01:dir=0;break;}亮灯P2输出:xxxx0001xxxx0010xxxx0100xxxx1000LED循环流程LED状态码数组[]={0x01,0x02,0x04,0x08}分析——搞清全部逻辑关系总体关系(主函数)流程(键值函数)参考程序:#includereg51.hunsignedcharled[]={0x01,0x02,0x04,0x08};//从上到下的流水灯bitrun,dir;unsignedchartemp,i;voiddelay(unsignedintz){unsignedintx,y;for(x=z;x0;x--)for(y=125;y0;y--);}voidmain(){while(1){temp=P0&0x03;switch(temp){case0x02:run=1;dir=1;//启动,自上往下break;case0x01:dir=0;//自下往上break;}if(run==1){if(dir==1)for(i=0;i=3;i++){P2=led[i];delay(200);}elsefor(i=4;i=1;i--){P2=led[i-1];delay(200);}}elseP2=0;}}实例采用共阴极的数码管实现功能要求:当按键按下时显示“L2”,松开时显示“H3”独立按键+数码管综合算出L2H3的段码分别为:0x38,0x5b,0x76,0x4f位选信号构成位码:0xfe,0xfd参考程序#includereg52.h#defineuintunsignedint#defineucharunsignedcharucharduan[]={0x38,0x5b,0x76,0x4f};//共阴L2H3ucharwei[]={0xfe,0xfd};sbitbutton=P1^6;voiddelay(uintz){uintx,y;for(x=z;x0;x--)for(y=125;y0;y--);}voidmain(){uchari;while(1){if(button==0)delay(10);if(button==0)for(i=0;i2;i++){P3=wei[i];P2=duan[i];delay(10);}elsefor(i=0;i2;i++){P3=wei[i];P2=duan[i+2];delay(10);}}}运行效果2、行列式键盘原理与编程独立式键盘的电路简单,易于编程,但占用的IO口线较多,当需要较多按键时可能产生IO资源紧张问题。独立式键盘P1.0P1.1P1.2P1.3P1.4P1.5P1.6P1.7+5V10kΩ10kΩ10kΩ10kΩ89S51当键盘上没有键闭合时,所有的行线和列线断开,列线都呈高电平。当键盘上某一个键闭合时,则该键所对应的列线与行线短路。此时列线的电平由相应的行线的电位所决定。行列式键盘——将IO口分为行线和列线,按键跨接在行线和列线上,列线通过上拉电阻接正电源。和行线连接的单片机端口,作为输出和列线连接的单片机端口,作为输入键盘扫描原理(以P3口接4×4键盘为例)①判断是否有键压下写P3端口0xf0(行线电平=0,列线电平=1)读P3端口:若P3=0xf0→无按键压下,不必后续判断;若P3≠0xf0→有键压下键盘扫描原理(以P3口接4×4键盘为例)②去除键的机械抖动其方法为:当判别到键盘上有键闭合后,延时一段时间再判别键盘的状态,若仍有键闭合,则认为键盘上有一个键处于稳定的闭合状态,否则认为键抖动。③判别闭合键的键值其方法为:对键盘的行线进行扫描,P3口依次循环输出0xfe、0xfd、0xfb和0xf7,相应地读P3口,若高4位P3.7~P3.4全为“1”,则说明该行上没有键闭合;否则,这一行上有键闭合,而且就是行线为0,列线为0的交叉键。高4位和低四位合并即得到键模。键模——按键压下时形成的电平编码值键值——按键的人为定义值整个4x4键盘的键模:0xee、0xde、0xbe、0x7e0xed、0xdd、0xbd、0x7d0xeb、0xdb、0xbb、0x7b0xe7、0xd7、0xb7、0x77第一行的键模:11101110、11011110、10111110、01111110④形成压下键的键模将各键的键模依次存放在一个数组中,其顺序号就是键值。利用循环变量i控制比对过程,两者相等时的i就是闭合键的键值。行列式键盘的特点:占用IO口线少,但软件过程复杂。Unsignedcharkey_val[]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77}for(i=0;i16;i++){if(key_val[i]==P3)returni;}实例行列式键盘要求按下任意按键后,数码管上显示该键的键值(0~F)参考程序#includereg51.hunsignedcharduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};unsignedcharkey_val[]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77};unsignedcharkey_scan[]={0xfe,0xfd,0xfb,0xf7};voiddelay(unsignedintz){unsignedintx,y;for(x=z;x0;x--)for(y=125;y0;y--);}voidmain(){unsignedchari,j;P2=0;while(1){P3=0xf0;if(P3!=0xf0){delay(10);if(P3!=0xf0)for(i=0;i4;i++){P3=key_scan[i];for(j=0;j16;j++if(key_val[j]==P3)P2=duan[j];}}}}实例运行效果