4*4键盘程序readkeyboard:begin: acall key_onjnz delayajmp readkeyboarddelay:acall delay10msacall key_onjnz key_numajmp beginkey_num:acall key_panl a,#0FFhjz beginacall key_ccodepush akey_off:acall key_onjnz key_offpop aretkey_on: mov a,#00horl a,#0fhmov p1,amov a,p1orl a,#0f0hcpl aretkey_p: mov r7,#0efhl_loop:mov a,r7mov p1,amov a,p1orl a,#0f0hmov r6,acpl ajz nextajmp key_cnext: mov a,r7jnb acc.7,errorrl amov r7,aajmp l_looperror:mov a,#00hretkey_c:mov r2,#00hmov r3,#00hmov a,r6mov r5,#04hagain1:jnb acc.0,out1rr ainc r2djnz r5, again1out1: inc r2mov a,r7mov r5,#04hagain2:jnb acc.4,out2rr ainc r3djnz r5,again2out2: inc r3mov a, r2swap aadd a,r3retkey_ccode:push aswap aanl a,#0fhdec arl a ;行号乘4rl amov r7,apop aanl a,#0fhdec aadd a,r7retdelay10ms:anl tmod,#0f0horl tmod,#01hmov th0,#0d8hmov tl0,#0f0hsetb tr0wait:jbc tf0,overajmp waitclr tr0over:ret单片机键盘设计(二)从电路或软件的角度应解决的问题软件消抖:如果按键较多,硬件消抖将无法胜任,常采用软件消抖。
通常采用软件延时的方法:在第一次检测到有键按下时,执行一段延时10ms的子程序后,再确认电平是否仍保持闭合状态电平,如果保持闭合状态电平,则确认真正有键按下,进行相应处理工作,消除了抖动的影响。
(这种消除抖动影响的软件措施是切实可行的。
)2.采取串键保护措施。
串键:是指同时有一个以上的键按下,串键会引起CPU错误响应。
通常采取的策略:单键按下有效,多键同时按下无效。
3.处理连击。
连击:是一次按键产生多次击键的效果。
要有对按键释放的处理,为了消除连击,使得一次按键只产生一次键功能的执行(不管一次按键持续的时间多长,仅采样一个数据)。
否则的话,键功能程序的执行次数将是不可预知,由按键时间决定。
连击是可以利用的。
连击对于用计数法设计的多功能键特别有效。
三、键盘工作方式单片及应用系统中,键盘扫描只是CPU的工作内容之一。
CPU忙于各项任务时,如何兼顾键盘的输入,取决于键盘的工作方式。
考虑仪表系统中CPU任务的份量,来确定键盘的工作方式。
键盘的工作方式选取的原则是:既要保证能及时响应按键的操作,又不过多的占用CPU的工作时间。
键盘的工作方式有:查询方式(编程扫描,定时扫描方式)、中断扫描方式。
四、键盘电路结构(一)独立式按键接口设计优点:电路配置灵活,软件结构简单。
此键盘是用于按键较少或操作速度较高的场合。
也可以用扩展I/O口搭接独立式按键接口电路,可采用8255扩展I/O口,用三态缓冲器扩展。
这两种配接方式,都是把按键当作外部RAM某一工作单元的位来对待,通过读片外RAM 的方法,识别按键的工作状态。
上电路中独立式按键电路,各按键开关均采用了上拉电阻,是为了保证在按键断开时,各I/O有确定的高电平。
如输入口线内部已有上拉电阻,则外电路的上拉电阻可省去。
(二)矩阵式键盘接口设计矩阵式键盘适用于按键数量较多的场合,由行线和列线组成,按键位于行列的交叉点上。
节省I/O口。
矩阵键盘工作原理:行线通过上拉电阻接到+5V上。
无按键,行线处于高电平状态,有键按下,行线电平状态将由与此行线相连的列线电平决定。
列线电平为低,则行线电平为低;列线电平为高,则行线电平为高。
五、双功能及多功能键设计在单片机应用系统中,为简化硬件线路,缩小整个系统的规模,总希望设置最少的按键,获得最多的控制功能。
矩阵键盘与独立式按键键盘相比,硬件电路大大节省。
可通过软件的方法让一键具有多功能。
方法:选择一个RAM工作单元,对某一个按键进行按键计数,根据不同计数值,转到子程序。
这种计数多功能键最好与显示器结合用,以便知道当前计数值,同时配合一个启动键。
复合键是使用软件实现一键多功能的另一个途径。
所谓复合键,就是两个或两个以上的键的联合,当这些键同时按下时,才能执行相应的功能程序。
实际情况做不到“同时按下”,他们的时间差别可以长到50ms,解决策略是:定义一个或两个引导键,这些引导键按下时没什么意义,执行空操作。
引导键的例子:微机键盘上的CTRL、SHIFT、ALT。
缺点:一是操作变得复杂,二是操作时间变长。
多功能键的利用,应具体情况具体分析。
要求速度的场合最好做一键一功能。
如果系统功能很多,一键一功能不现实,可采取一键多功能。
六、功能开关及拨码盘接口设计设计原因:键盘输入灵活性大,操纵方便。
但某些重要功能或数据由键盘输入,误操作将产生一些不良后果。
因此常设定静态开关的方法来执行这些功能或输入数据。
静态开关一经设定,将不再改变,一直维持设定的开关状态。
通常这些开关状态是在单片机系统加电时由CPU读入内存RAM的,以后CPU将不再关注这些开关的状态,因此,即使加电后,这些开关的状态发生变化,也不会影响CPU的正常工作,只有在下一次加电时,这些新状态才能生效。
第一,功能开关:主要是根据开关的状态执行一些重要的功能。
第二,拨码盘:单片机应用系统中,有时要输入一些控制参数,这些参数一经设定,将维持不变,除非给系统断电后重新设定。
这时使用数字拨码盘既简单直观,又方便可靠。
七、按键介绍常用的按键有三种:机械触点式按键、导电橡胶式和柔性按键(又称触摸式键盘)。
机械触点式按键是利用弹性使键复位,手感明显,连线清晰,工艺简单,适合单件制造。
但是触点处易侵入灰尘而导致接触不良,体积相对较大。
导电橡胶按键是利用橡胶的弹性来复位,通过压制的方法把面板上所有的按键制成一块,体积小,装配方便,适合批量生产。
但是时间长了,橡胶老化而使弹力下降,同时易侵入灰尘。
柔性按键是近年来迅速发展的一种新型按键,可以分为凸球型和平面型两种。
凸球型动作幅度触感明显,富有立体感,但制造工艺相对复杂;平面型幅度微小,触感较弱,但工艺简单,寿命长。
柔性按键最大特点是防尘、防潮、耐蚀,外形美观,装嵌方便。
而且外形和面板的布局、色彩、键距可按照整机的要求来设计。
八、单片机系统键盘设计实例键盘工作方式采用定时扫描方式。
采用定时器T0定时,CPU每隔200ms扫描键盘一次,即通过读取573的输出数据,识别按键的工作状态。
对于重键(串键:指同时有一个以上的键按下),采用软件提供保护,当判断为一个以上的键按下,则不处理,返回重新进行监测。
只有监测到一个键按下时,才判断键值,执行相应键处理工作。
键盘对液晶显示的控制是通过显示画面的页码作为接口参数来完成的。
在每一页中,键盘对数据的修改是通过对按键次数的计算作为接口参数来实现的。
具体例程如下:void keyscan() /*键盘扫描*/{ucher data newz ,temp,pat;if(time_out){ACC=MJP; /*读取573数据*/temp=ACC&0x0f, /*取低四位*/if(temp!=0x0f) /*有键按下*/{msec(10); /*延时10MS*/ACC=MJP; /*读取573数据*/temp=ACC&0x0fif(temp=0x0f){newz=temp; /*读取新键值*/pat=newz^old; /*键值有无变化*/if(pat)>0) /*有变化*/{old=newz; /*原键值等于新键值*/keymana(); /*调键散转程序*/}else;}else;}elsr;old=temp; /*原键值不变*/time_out=0 /*标志位置零*/}esel;}4*4键盘程序; 0 1 2 3 --P30; 4 5 6 7 --P31; 8 9 A B --P32 ; C D E F --P33 ; P34 P35 P36 P37 ORG 0000hLJMP MAINORG 0030hMAIN:MOV DPTR,#TABLCALL KEYMOVC A,@A+DPTR MOV P0,A CLR P1.3LJMP MAINKEY: LCALL KSJNZ K1LCALL DELAY2 AJMP KEYK1: LCALL DELAY2LCALL KSJNZ K2AJMP KEYK2: MOV R2,#0EFHMOV R4,#00HK3: MOV P3,R2L6: JB P3.0,L1MOV A,#00H AJMP LKL1: JB P3.1,L2MOV A,#04HAJMP LKL2: JB P3.2,L3MOV A,#08HAJMP LKL3: JB P3.3,NEXT MOV A,#0cH LK: ADD A,R4PUSH ACC K4: LCALL DELAY2 LCALL KSJNZ K4POP ACCRETNEXT:INC R4MOV A,R2JNB ACC.7,KEYRL AMOV R2,AAJMP K3KS: MOV P3,#0FHMOV A,P3XRL A,#0FHRETDELAY2: MOV R5,#08HL7: MOV R6,#0FAHL8: DJNZ R6,L8DJNZ R5,L7RETTAB:DB 0C0H;0DB 0F9H;1DB 0A4H;2DB 0B0H;3DB 099H;4DB 092H;5DB 082H;6DB 0F8H;7DB 080H;8DB 090H;9DB 088H;ADB 083H;bDB 0C6H;CDB 0A1H;dDB 086H;EDB 08EH;FEND4X4矩阵键盘扫描汇编程序PROC KEYCHKKEYNAME DATA 40H;(b7-b5纪录按键状态,b4位为有效位, ;b3-b0纪录按键)KEYRTIME DATA 43HSIGNAL DATA 50HKEY EQU P3KEYPL EQU P0.6RTIME EQU 30KEYCHK: MOV KEY,#0FHMOV A,KEYCJNE A,#0FH,NEXT1; CLR CNEXT1:; SETB CMOV A,KEYNAMEANL KEYNAME,#1FHRRC AANL A,#0E0HORL KEYNAME,ACJNE A,#0C0H,NEXT2SJMP KEYSCANNEXT2: CJNE A,#0E0H,NEXT3SJMP WAITNEXT3:CJNE A,#0A0H,EXITORL KEYNAME,#0E0H WAIT: MOV A,KEYRTIMEJNZ EXITKEYSCAN: MOV R1,#0MOV R3,#11110111B LOOP: MOV A,R3RL AMOV R3,AMOV KEY,AMOV A,KEYORL A,#0F0HCJNE A,#0FFH,NEXT31INC R1CJNE R1,#4,LOOPSJMP EXITNEXT31: JB ACC.0,NEXT32MOV R2,#0SJMP NEXT5NEXT32:JB ACC.1,NEXT33MOV R2,#1SJMP NEXT5NEXT33:JB ACC.2,NEXT34MOV R2,#2SJMP NEXT5NEXT34:MOV R2,#3NEXT5: MOV A,R1RL ARL AADD A,R2MOV DPTR,#KEYTABMOVC A,@A+DPTRANL KEYNAME,#0E0HORL KEYNAME,AMOV KEYRTIME,#RTIMECLR KEYPLMOV SIGNAL,#10EXIT: MOV KEY,#0FFHRETKEYTAB: ;//=按键名称表=DB 1AH ;扫描码0,对应ADB 1BH ;扫描码1,对应BDB 1CH ;扫描码2,对应CDB 1DH ;扫描码3,对应DDB 11H ;扫描码4,对应1DB 14H ;扫描码5,对应4DB 17H ;扫描码6,对应7DB 1EH ;扫描码7,对应EDB 12H ;扫描码8,对应2DB 15H ;扫描码9,对应5DB 18H ;扫描码A,对应8DB 10H ;扫描码B,对应0DB 13H ;扫描码C,对应3DB 16H ;扫描码D,对应6DB 19H ;扫描码E,对应9DB 1FH ;扫描码F,对应FEND4×4矩阵式键盘org 0000hljmp startorg 0030hstart:mov dptr,#tablemov r3,#4mov p2,#00hlcall keyscanresponse:movc a,@a+dptrmov p0,asetb p2.1keyscan:lcall keypress;jnz k1jmp keyscank1: lcall delaylcall keypressjnz k2jmp keyscank2: mov r0,#00h mov r1,#00h mov p1,#0efh mov a,p1anl a,#0fh; mov r2,axrl a,#0fhjnz k3mov p1,#0dfh mov r0,#01h mov a,p1anl a,#0fhmov r2,axrl a,#0fhjnz k3mov p1,#0bfh; mov r0,#02hmov a,p1anl a,#0fh; mov r2,axrl a,#0fhjnz k3mov p1,#07fh; mov r0,#03h; mov a,p1anl a,#0fh; mov r2,axrl a,#0fhjnz k3jmp keyscank3: mov a,r2rrc a ;jnc k4 ;rrc ajnc k5 ;rrc ajnc k6 ;jnb p1.3,$mov r1,#03hmov a,r0mov b,r3mul abadd a,r1jmp responsek4: jnb p1.0,$ ; mov r1,#00hmov a,r0mov b,#4mul abadd a,r1jmp responsek5: jnb p1.1,$mov r1,#01hmov a,r0mov b,#4mul abadd a,r1jmp responsek6: jnb p1.2,$mov r1,#02hmov a,r0mov b,#4mul abadd a,r1jmp response keypress:mov p1,#0fh mov a,p1xrl a,#0fhretdelay: mov r7,#50d1: mov r6,#248djnz r6,$djnz r7,d1rettable: db 3fh,06h,5bh,4fh;0 1 2 366h,6dh,7dh,07h;4 5 6 77fh,6fh,77h,7ch;8 9 a b39h,5eh,79h,71h;c d e fend *********4×4矩阵式键盘KEYNAME DATA 40HORG 0000HLJMP MAINORG 0030HMAIN:MOV SP, #80HCLR F0LOOP:LCALL KEYCHKLCALL KEYSCANSJMP LOOPKEYCHK:MOV P1, #0F0HMOV A, P1CJNE A, #0F0H, $+3LCALL DELAY_10MSMOV A, P1CJNE A, #0F0H, NEXT11CLR F0SJMP EXIT1NEXT11:SETB F0EXIT1:RETKEYSCAN:JNB F0, EXIT2MOV R7, #4MOV R5, #0MOV R6, #01111111BLOOP1:MOV A, R6RL AMOV R6, AMOV P1, AMOV A, P1ANL A, #0F0HXRL A, #0F0HJNZ NEXT21INC R5DJNZ R7, LOOP1SJMP EXIT2NEXT21:JNB Acc.4, NEXT22MOV R4, #0SJMP NEXT25NEXT22:JNB Acc.5, NEXT23MOV R4, #1SJMP NEXT25NEXT23:JNB Acc.6, NEXT24MOV R4, #2SJMP NEXT25NEXT24:MOV R4, #3NEXT25:MOV A, R5RL ARL AADD A, R4MOV DPTR, #KEYTABMOVC A, @A+DPTRMOV KEYNAME, AEXIT2:RETDELAY_10MS:SETB RS1SETB RS0MOV R2,#20DELAY0:MOV R3,#250DJNZ R3,$DJNZ R2,DELAY0RETKEYTAB:DB 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15END4X4键盘输入数码管移位显示1 #include <REG51.H>#include<intrins.h>#include<bin.h>uchar num,num1,temp;sbit dula=P2^6;sbit wela=P2^7;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};uchar keyscan();void delay(uchar z){ //10MS延时uint x;for(z;z!=0;z--)for(x=1250;x!=0;x--);}void main(){wela=1;dula=0;P0=0xc0;num=17;P0=0;wela=0; //所有数码管不亮dula=1;while(1){num1=keyscan();P0=table[num1-1];}}uchar keyscan(){P3=0xf0;temp=P3;while(temp!=0xf0){delay(1);temp=P3;while(temp!=0xf0){P3=0xfe;temp=P3&0xf0;if(temp!=0xf0){temp=P3;switch(temp){case 0xee:num=1,temp=0xf0; break;case 0xde:num=2,temp=0xf0; break;case 0xbe:num=3,temp=0xf0; break;case 0x7e:num=4,temp=0xf0; break;// default:temp=0xf0;}P3=0xfd;temp=P3&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xed:num=5,temp=0xf0;break;case 0xdd:num=6,temp=0xf0;break;case 0xbd:num=7,temp=0xf0;break;case 0x7d:num=8,temp=0xf0;break;// default:temp=0xf0;}}P3=0xfb;temp=P3&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xeb:num=9,temp=0xf0;break; case 0xdb:num=10,temp=0xf0;break; case 0xbb:num=11,temp=0xf0;break; case 0x7b:num=12,temp=0xf0;break;// default:temp=0xf0;}}P3=0xf7;temp=P3;temp&=0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xe7:num=13,temp=0xf0;break; case 0xd7:num=14,temp=0xf0;break; case 0xb7:num=15,temp=0xf0;break; case 0x77:num=16,temp=0xf0;break;// default:temp=0xf0;}}}return (num);}4X4键盘输入数码管移位显示2 #include <REG51.H>#include<intrins.h>#include<bin.h>uchar num,num1,num2,temp;uchar a,b,c,d,e,f;sbit dula=P2^6;sbit wela=P2^7;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};uchar code table1[]={0xdf,0xef,0xf7,0xfb,0xfd,0xfe} ;uchar keyscan();void display();void delay(uchar z){uint x;for(z;z!=0;z--)for(x=625;x!=0;x--);}void inti(){num1=0;a=b=c=d=e=f=16;wela=0;dula=0;}void main(){inti();while(1){keyscan();switch(num1){case 1:a=num-1;break;case 2:b=num-1;break;case 3:c=num-1;break;case 4:d=num-1;break;case 5:e=num-1;break;case 6:f=num-1;break;// default:;}display();}}uchar keyscan(){P3=0xf0;temp=P3;while(temp!=0xf0){delay(1);temp=P3;while(temp!=0xf0){P3=0xfe;temp=P3&0xf0;if(temp!=0xf0){temp=P3;switch(temp){case 0xee:num=1,temp=0xf0; break;case 0xde:num=2,temp=0xf0; break;case 0xbe:num=3,temp=0xf0; break;case 0x7e:num=4,temp=0xf0; break;// default:temp=0xf0;}}P3=0xfd; //temp=P3&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xed:num=5,temp=0xf0;break;case 0xdd:num=6,temp=0xf0;break;case 0xbd:num=7,temp=0xf0;break;case 0x7d:num=8,temp=0xf0;break;// default:temp=0xf0;}}P3=0xfb;temp=P3&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xeb:num=9,temp=0xf0;break;case 0xdb:num=10,temp=0xf0;break;case 0xbb:num=11,temp=0xf0;break;case 0x7b:num=12,temp=0xf0;break;// default:temp=0xf0;}}P3=0xf7;temp=P3;temp&=0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xe7:num=13,temp=0xf0;break;case 0xd7:num=14,temp=0xf0;break;case 0xb7:num=15,temp=0xf0;break;case 0x77:num=16,temp=0xf0;break;// default:temp=0xf0;}}P3=0xf0;while(P3!=0xf0);delay(1);while(P3!=0xf0);}if(num1==6){num1=0;}num1++;}return (num);}void display(){ //最右第1个数码管,下同。