OUTBIT EQU 8002H ;端口地址初始化
OUTSEG EQU 8004H
HIN EQU 8001H
LEDBUF EQU 30H
ORG 0000H
LJMP START
ORG 0100H
LEDMAP: ;短码表
DB 3FH,06H,5BH,4FH
DB 66H,6DH,7DH,07H
DB 7FH,6FH,77H,7CH
DB 39H,5EH,79H,71H
DELAY: MOV 19H,#10
DEY1: MOV 18H,#50 ;延蔇EY2: DJNZ 18H,DEY2
DJNZ 19H,DEY1
RET
DISPLAY: ;显示子程序
MOV DPTR,#OUTBIT
MOV A,#0
MOVX @DPTR,A
MOV A,R5 ;R4--段码
MOV DPTR,#OUTSEG
MOVX @DPTR,A
MOV DPTR,#OUTBIT
MOV A,R2 ;R2--位码
MOVX @DPTR,A
ACALL DELAY
MOV DPTR,#OUTBIT
MOV A,#0
MOVX @DPTR,A
RET
TESTKEY: MOV DPTR,#OUTBIT ;检测键盘
MOV A,#00H
MOVX @DPTR,A ;输出列置0
MOV DPTR,#HIN
MOVX A,@DPTR ;读入键盘状态
CPL A
ANL A,#0FH
RET
KEYTABLE: DB 16H,15H,14H,0FFH ;键码定义
DB 13H,12H,11H,10H
DB 0DH,0CH,0BH,0AH
DB 0EH,03H,06H,09H
DB 0FH,02H,05H,08H
DB 00H,01H,04H,07H
GETKEY: MOV DPTR,#OUTBIT ;计算键编号
MOV P2,DPH
MOV R1,#HIN ;R1行地址
MOV R3,#20H ; R2列码
MOV R7,#6
KLOOP: MOV A,R3
CPL A
MOVX @DPTR,A ;第一列置0
CPL A
RR A
MOV R3,A ;下一列
MOVX A,@R1 ; 读该列状态
CPL A
ANL A,#0FH ;屏蔽高四位
JNZ GOON1
DJNZ R7,KLOOP
MOV R7,#0FFH ;无键按下返回0FFH
SJMP EXIT
GOON1: MOV R3,A ;编号=列*4+行
MOV A,R7
DEC A
RL A
RL A
MOV R7,A ;R0=(R7-1)*4
MOV A,R3 ;R2为读入列值
MOV R2,#4
LOOPC: RRC A ;右移计算行值
JC EXIT ;R0=R0+行值
INC R7
DJNZ R3,LOOPC
EXIT: MOV A,R7 ;取键编号
MOV DPTR,#KEYTABLE
MOVC A,@A+DPTR
MOV @R0,A ;存键值R0中
WAITRELEASE: ;等待键释放
MOV DPTR,#OUTBIT
CLR A
MOVX @DPTR,A
ACALL DELAY
ACALL TESTKEY
JNZ WAITRELEASE
MOV A,@R0 ;键值存入A
RET
ADDY: MOV 12H,R0
CLR C ;加法
MOV R7,#4
ADDY1: MOV A,@R0
ADDC A,@R1
MOV @R0,A ;结果存入R0
INC R0
INC R1
DJNZ R7,ADDY1
MOV R7,#5
ACALL CHANG
RET
SUBBY: MOV 12H,R0
CLR C ;减法
MOV R7,#2
SUB1: MOV A,@R1
SUBB A,@R0
JNC N1
ADD A,#10
SETB C
N1: MOV @R0,A
INC R0
INC R1
DJNZ R7,SUB1
MOV R0,12H
RET
MULY: MOV 12H,R0
MOV R3,#0 ;乘法
MOV 15H,@R0 ;另存乘数
INC R0
MOV 16H,@R0
DEC R0
MOV R2,#2
MUL1: MOV A,@R1
MOV B,@R0
MUL AB
MOV @R0,A
INC R0
DJNZ R2,MUL1
DEC R0
INC R1
MOV B,15H
MOV R2,#2
MUL2: MOV A,@R1
MUL AB
ADD A,@R0
MOV @R0,A
INC R0
MOV A,#0
ADDC A,#0
MOV @R0,A
MOV B,16H
DJNZ R2,MUL2
MOV R7,#4
ACALL CHANG
RET
CHANG: MOV R0,12H ;转化为十进制
MOV R3,#0
C1: MOV A,@R0
ADD A,R3
MOV B,#10
DIV AB
XCH A,B
MOV @R0,A
INC R0
MOV R3,B
DJNZ R7,C1
MOV R0,12H
RET
LEDBUFY: JC NEXT1 ;数据缓冲子程序
SJMP NEXT2
NEXT1: MOV R5,#40H ;负数
MOV R2,#20H
ACALL DISPLAY
MOV R2,17H
NEXT2: MOV A,@R0
MOV DPTR,#LEDMAP
MOVC A,@A+DPTR
MOV R5,A
ACALL DISPLAY
MOV A,R2
RR A
MOV R2,A
DEC R0
DJNZ R6,NEXT2
RET
START: CLR C ;开始
MOV R0,#LEDBUF ;R0--数据缓冲地址
MOV R6,#0
MOV R3,#30 ;初始化参数
K1: MOV @R0,#00H
INC R0
DJNZ R3,K1
MOV R0,#LEDBUF+20 ;缓冲区清零
DISPL: MOV 10H,R0 ;保护R0,R6
MOV 11H,R6
MOV R2,#1
CJNE R6,#0,Y1
SJMP Y3 ;无任何键按下
Y1: MOV A,R0
ADD A,R6
MOV R0,A ;数据高位地址送R0
MOV A,R2
RRC A
Y2: RLC A
DJNZ R6,Y2
MOV R2,A ;位码移到高位
MOV R6,11H
SJMP Y4
Y3: MOV R6,#01H
Y4: MOV 17H,R2
ACALL LEDBUFY ;数据送缓冲区显示
MOV R6,11H
MOV R0,10H
TESTY: ACALL TESTKEY
ACALL DELAY ;测试键盘
JZ DISPL ;无键按下,动态显示缓冲区内容
ACALL GETKEY ;有键输入
DEC R0
K2: CJNE A,#0AH,K3 ;确认键值
SJMP NEXT ;功能键“+”
K3: JNC K4
INC R6
SJMP DISPL
K4: CJNE A,#0FH,K5
SJMP START ;清零键
K5: CJNE A,#0BH,K6 ;功能键“-”
SJMP NEXT
K6: CJNE A,#0CH,K7 ;功能键“*”
NEXT: MOV R4,A ;功能键“+,-,*”,并保存入R4
MOV A,R0
INC A
INC A
MOV 1FH,A
MOV R0,#LEDBUF+10 ;赋下一个操作数缓冲地址
MOV R6,#0 ; 计数清零
SJMP TESTY ;等待数据输入
K7: CJNE A,#0EH,K8 ;功能键“=”
EQUY: INC R0
INC R0
MOV R1,1FH
CJNE R4,#0AH,LOOP1 ;测试上一次功能键
ACALL ADDY
DEC R0 ;加法
MOV R6,#5 ;五个缓冲单元
SJMP DISPL
LOOP1: CJNE R4,#0BH,LOOP2
ACALL SUBBY
DEC R0 ;减法
MOV R6,#2 ;两个缓冲单元
SJMP DISPL
LOOP2: ACALL MULY ;乘法
DEC R0
MOV R6,#4 ;四个缓冲单元
SJMP DISPL ;送数入显示缓冲区
K8: INC R0
MOV @R0,#0
SJMP TESTY ;继续测试键盘
END