4 设计实例
下面为一设计实例,要求所设计的小键盘输出F1、F2、 F3、F4、Page UP、Page Down、Esc、En ter 8个PC/AT PS/2键盘信号。8个按键的一端分别接P3.7、P1.0~P1.6端口,8个按键的另一端为公共 接地端。
全部程序如下所示:
/* CRYSTAL IS 20MHz, keycode clock is 12.5kHz,*/
KEY: DO;
$NOLIST
$INCLUDE (REG51.DCL)
$LIST
DECLARE WDI LITERALLY ''P3_0'';
DECLARE SW1 LITERALLY ''P3_7'';
DECLARE SW2 LITERALLY ''P1_0'';
DECLARE SW3 LITERALLY ''P1_1'';
DECLARE SW4 LITERALLY ''P1_2'';
DECLARE SW5 LITERALLY ''P1_3'';
DECLARE SW6 LITERALLY ''P1_4'';
DECLARE SW7 LITERALLY ''P1_5'';
DECLARE SW8 LITERALLY ''P1_6'';
DECLARE KEY$DATA LITERALLY ''P3_1'';
DECLARE KEY$CLK LITERALLY ''P1_7'';
DECLARE (DK,KEY$CODE,PARITY,SHIFT$REG,NUMBER,DI,DN) BYTE;
DECLARE (T0$INT) BIT;
/******* INTERRUPT OF TIMER 1 ********/
TIMER1: PROCEDURE INTERRUPT 3 USING 1;
DISABLE;
WDI=1;
DK=0;
TH1=0BEH;
TL1=0E6H;
DN=800;
IF SW1=0 THEN
DO;
DI=DN;
DO WHILE DI>0;
DI=DI-1;
END;
IF SW1=0 THEN DK=1;
KEY$CODE=5AH; /*Enter*/
PARITY=0FFH;
END;
IF SW2=0 THEN
DO;
DI=DN;
DO WHILE DI>0;
DI=DI-1;
END;
IF SW2=0 THEN
DO;
DK=2;
KEY$CODE=76H; /*Esc*/
PARITY=00H;
END;
IF SW3=0 THEN
DO;
DI=DN;
DO WHILE DI>0;
DI=DI-1;
END;
IF SW3=0 THEN DK=3;
KEY$CODE=75H; /*8/up*/
PARITY=00H;
END;
IF SW4=0 THEN
DO;
DI=DN;
DO WHILE DI>0;
DI=DI-1;
END;
IF SW4=0 THEN DK=4;
KEY$CODE=72H; /*2/down*/
PARITY=0FFH;
END;
IF SW5=0 THEN
DO;
DI=DN;
DO WHILE DI>0;
DI=DI-1;
END;
IF SW5=0 THEN DK=5;
KEY$CODE=06H; /*F2*/
PARITY=0FFH;
END;
IF SW6=0 THEN
DO;
DI=DN;
DO WHILE DI>0;
DI=DI-1;
END;
IF SW6=0 THEN DK=6;
KEY$CODE=04H; /*F3*/
PARITY=00H;
END;
IF SW7=0 THEN
DO;
DI=DN;
DO WHILE DI>0;
DI=DI-1;
END;
IF SW7=0 THEN DK=7;
KEY$CODE=0CH; /*F4*/
PARITY=0FFH;
END;
IF SW8=0 THEN
DO;
DI=DN;
DO WHILE DI>0;
DI=DI-1;
END;
IF SW8=0 THEN DK=8;
KEY$CODE=05H; /*F1*/
PARITY=0FFH;
END;
WDI=0;
DN=0;
T1$RET: ENABLE;
END;
/****INTERRUPT OF TIMER 0****/
TIMER0: PROCEDURE INTERRUPT 1 USING 2;
DISABLE;
WDI=1;
IF NUMBER=0 THEN
DO;
KEY$CLK=0;
KEY$DATA=1;
END;
ELSE
DO;
KEY$CLK=1;
DI=4;
DO WHILE DI>0;
DI=DI-1;
END;
IF (SHIFT$REG AND 01H)=0 THEN KEY$DATA=0;
IF (SHIFT$REG AND 01H)=1 THEN KEY$DATA=1;
DI=4;
DO WHILE DI>0;
DI=DI-1;
END;
KEY$CLK=0;
NUMBER=NUMBER-1;
END;
T0$RET: T0$INT=1;
WDI=0;
ENABLE;
END;
/*************MAIN PROGRAM***********/
MAIN_PRG: SW1=1; /**** INIT PORT ****/
SW2=1;
SW3=1;
SW4=1;
SW5=1;
SW6=1;
SW7=1;
SW8=1;
KEY$CLK=0;
KEY$DATA=0;
KEY$CODE=00H;
PARITY=00H;
SHIFT$REG=00H;
NUMBER=11;
T0$INT=0;
DK=0;
DI=0;
DN=0;
TMOD=10H; /*T1 MODE 1*/
IE=0C8H; /****T1 interrupt enable ****
TCON=40H; /****T1 begin work ****/
TH1=0BEH; /*T1 100Hz */
TL1=0E6H;
TH0=7BH; /*T0 16kHz*/
TL0=7BH;
ENABLE;
MAIN$LOOP: IF DK=0 THEN GOTO MAIN$END;
TMOD=02H; /*T0 BEGIN WORK*/
IE=0C2H; /*T1 STOP WORK*/
TCON=10H;
T0$INT=0;
SHIFT$REG=00H;
WAIT1: IF T0$INT=0 THEN GOTO WAIT1; /*send S bit*/
T0$INT=0;
SHIFT$REG=KEY$CODE;
WAIT2: IF T0$INT=0 THEN GOTO WAIT2; /*send Key$code*/
SHIFT$REG=SHR(SHIFT$REG,1);
T0$INT=0;
IF NUMBER>2 THEN GOTO WAIT2;
SHIFT$REG=PARITY;
WAIT3: IF T0$INT=0 THEN GOTO WAIT3; /*send parity bit*/
T0$INT=0;
SHIFT$REG=0FFH;
WAIT4: IF T0$INT=0 THEN GOTO WAIT4; /*send ST bit*/
T0$INT=0;
DK=0;
WAIT5: IF T0$INT=0 THEN GOTO WAIT5; /* KEY$CLK=0 for 300us*/
T0$INT=0;
DK=DK+1;
IF DK<4 THEN GOTO WAIT5;
/****************SEND 0F0H**************/
KEY$CLK=1;
KEY$DATA=1;
T0$INT=0;
DK=0;
IE=00H; /*T0 STOP WORK*/
TCON=00H
TMOD=10H; /*T1 BEGAN WORK*/
IE=0C8H;
TCON=40H;
TH1=0BEH;
TL1=0E6H;
CALL TIME(200);
TMOD=02H; /*T0 BEGIN WORK*/
IE=0C2H; /*T1 STOP WORK*/
TCON=10H;
T0$INT=0;
NUMBER=11;
T0$INT=0;
SHIFT$REG=00H;
WAIT11: IF T0$INT=0 THEN GOTO WAIT11; /*send S bit*/
T0$INT=0;
SHIFT$REG=0F0H;
WAIT12: IF T0$INT=0 THEN GOTO WAIT12; /*send 0F0H code*/
SHIFT$REG=SHR(SHIFT$REG,1);
T0$INT=0;
IF NUMBER>2 THEN GOTO WAIT12;
SHIFT$REG=0FFH;
WAIT13: IF T0$INT=0 THEN GOTO WAIT13; /*send parity bit*/
T0$INT=0;
SHIFT$REG=0FFH;
WAIT14: IF T0$INT=0 THEN GOTO WAIT14; /*send ST bit*/
T0$INT=0;
DK=0;
WAIT15: IF T0$INT=0 THEN GOTO WAIT15; /* KEY$CLK=0 for 300us*/
T0$INT=0
DK=DK+1;
IF DK<4 THEN GOTO WAIT15;
/***************SEND KEY$CODE******************/
KEY$CLK=1;
KEY$DATA=1;
T0$INT=0;
DK=0;
IE=00H; /*T0 STOP WORK*/
TCON=00H;
TMOD=10H; /*T1 BEGAN WORK*/
IE=0C8H;
TCON=40H;
TH1=0BEH;
TL1=0E6H;
CALL TIME(200);
TMOD=02H; /*T0 BEGIN WORK*/
IE=0C2H; /*T1 STOP WORK*/
TCON=10H;
T0$INT=0;
NUMBER=11;
T0$INT=0;
SHIFT$REG=00H;
WAIT21: IF T0$INT=0 THEN GOTO WAIT21; /*send S bit*/
T0$INT=0;
SHIFT$REG=KEY$CODE;
WAIT22: T0$INT=0 THEN GOTO WAIT22; /*send Key$code*/
SHIFT$REG=SHR(SHIFT$REG,1);
T0$INT=0;
IF NUMBER>2 THEN GOTO WAIT22;
SHIFT$REG=PARITY;
WAIT23: IF T0$INT=0 THEN GOTO WAIT23; /*send parity bit*/
T0$INT=0;
SHIFT$REG=0FFH;
WAIT24: IF T0$INT=0 THEN GOTO WAIT24; /*send ST bit*/
T0$INT=0;
DK=0;
WAIT25: IF T0$INT=0 THEN GOTO WAIT25; /* KEY$CLK=0 for 300us*/
T0$INT=0;
DK=DK+1;
IF DK<4 THEN GOTO WAIT25;
KEY$CLK=1;
KEY$DATA=1;
T0$INT=0;
DK=0;
IE=00H; /*T0 STOP WORK*/
TCON=00H;
DO DI=1 TO 300; /*DELAY TIME*/
CALL TIME(20);
END;
MAIN$END: KEY$CLK=1;
KEY$DATA=1;
NUMBER=11;
SHIFT$REG=0;
GOTO MAIN$LOOP;
END KEY;
本文介绍的PC/AT键盘具有结构简单、设计灵活性强、易于编程、体积小、成本低的特点,并可 根据用户需要随意设计和布放,对使用工控机的各种测试与控制仪器具有通用性。
参考文献
1 ATMEL公司. AT89C2051 Data Sheet
2 MAXIM公司. MAX813L Data Sheet
3 马忠梅. 单片机的C语言应用程序设计. 北京:北京航空航天大学出版社,1999
更多技术资料文章可到 :
http://www.qlmcu.com/
http://www.qlmcu.com/dvbbs/index.asp
[此贴子已经被作者于2005-7-12 9:13:57编辑过]