LNUM EQU 0030H //将0030H定义为LNUM;
ORG 0000H //程序在储存器中存放的起始位置;
JMP START //跳转到START;
ORG 0100H //程序在储存器中存放的起始位置;
START: MOV SP,#5FH //初始化SP值为5FH;
MOV LNUM,#4 //共4行;
MOV P2,#9FH //初始化数码管显示为1;
CLR F0 //清零F0,初始化;
ST1: CALL MAKEY //单元矩阵键盘扫描子程序;
JNB F0,ST1 //F0为0时无键按下,继续扫描;
ANL A,#0FH //有键按下时,键号在A中;
MOV DPTR,#CODE_P2 //将CODE_P0定义的数据表的首地址送给DPTR;
MOVC A,@A+DPTR //查表;
MOV P2,A //显示所有按键的键号;
JMP ST1 //跳转到ST1;
MAKEY: CALL KEYHN //调用子程序KEYHN;
JNZ HAVE //有键按下;
JMP NRET //清零F0,并返回再次进行下面的程序;
HAVE: CALL D10ms //调用D10ms,延时10ms;
CALL KEYHN //延时后再判,去抖动;
JNZ TRUE //确认有按键按下;
JMP NRET //清零F0,并返回再次进行下面的程序;
TRUE: MOV R1,#0EFH //首列扫描字;
MOV R4,#0 //首列号;
SCAN: MOV A,R1 //将R1中的值送给给A;
MOV P1,A //将A中的值送给P1;
MOV A,P1 //将P1中的值送给A;
JB ACC.0,L1 //0行无键按下,转1行;
MOV A,#0 //0行首键号;
JMP KEYNUM //转键号计算;
L1: JB ACC.1,L2 //1行无键按下,转2行;
MOV A,#4 //1行首键号;
JMP KEYNUM //转键号计算;
L2: JB ACC.2,L3 //2行无键按下,转3行;
MOV A,#8 //2行首键号;
JMP KEYNUM //转键号计算;
L3: JB ACC.3,NEXT //3行无键按下,转下一行;
MOV A,#0CH //3行首键号;
KEYNUM: ADD A,R4 //键号=行首号+列号;
PUSH ACC //将ACC中数给SP中;
UPKEY: CALL KEYHN //调用子程序KEYHN;
JNZ UPKEY //等待键释放;
POP ACC //将SP中的数给SP中;
SETB F0 //置有键按下标志;
JMP HRET //跳转到HRET;
NRET: CLR F0 //清零有键按下标志;
HRET: RET //返回到调用子程序NRET的下面;
NEXT: INC R4 //R4自加1,下一列;
MOV A,R1 //将A中的数送给R1;
DJNZ LNUM,NDONE //若LUNM减1不为0,则跳转到NDONE;
//若LUNM减1为0,则程序往下执行;
JMP NRET //跳转到NRET;
NDONE: RL A //扫描字左移,准备扫描下一列;
MOV R1,A //置高四位全为0,低四位输入状态;
JMP SCAN //跳转到SCAN;
KEYHN: MOV P1,#0FH //置高四位全为0,低四位输入状态;
MOV A,P1 //将0FH送给A;
CPL A //将A中的数取反再送给A;
ANL A,#0FH //A的高四位清零,低四位输入状态;
RET //返回;
D10ms: MOV R5,#10 //10ms;
D1ms: MOV R4,#249 //
DL: NOP //空操作;
NOP //空操作;
DJNZ R4,DL //R4减1,若为0,则结束循环,程序往下执行;
//若不为0,则跳转到DL;
DJNZ R5,D1ms //R5减1,若为0,则结束循环,程序往下执行;
//若不为0,则跳转到D1ms;
RET //返回;
CODE_P2:DB 03H,9FH,25H,0DH,99H,49H,40H,1FH
DB 01H,09H,11H,0C1H,63H,85H,61H,71H //数码管显示数据表,0——F;
END //结束;
|