📄 success.asm
字号:
NEXT: RRC A ;调整待查列
JNC FIND ;被查列为低电平,按键找到,转出
INC R7 ;未找到,键号加1
DJNZ R3,NEXT ;被扫描行的待查列未完,转回NEXT
DJNZ R2,SCAN ;待扫描行数未完,转回SCAN
SJMP NOKEY ;未找到按键
FIND: MOV P1,#0F0H
LOOSEN: MOV A,P1
ORL A,#0FH
CPL A
JNZ LOOSEN ;以上5条全扫描,等待松按
SETB WKLED
LCALL DELAY100
CLR WKLED ;以上3条熄灭LED再点亮,表示获得按键
ACALL DISP ;显示键值
ACALL SEND ;发送键码
NOKEY: SETB EX0 ;开INT0中断,以便响应以后的其它按键
MOV P1,#0F0H ;置键盘行线P1.0-P1.3为0,作好响应按键的准备
RETI
;子程序---键号转换并向PC机发送按键,入口参数:R7=键号
SEND: MOV A,R7
MOV DPTR,#TAB_KBD
MOVC A,@A+DPTR ;发送键号对应的接通键码
ACALL SEND_B
MOV A,#0F0H ;发送断开键码F0
ACALL SEND_B
MOV A,R7
MOV DPTR,#TAB_KBD
MOVC A,@A+DPTR ;加发键号对应的接通键码
ACALL SEND_B
RET
TAB_KBD:DB 16H ;'1'的接通键码
DB 25H ;'4'的接通键码
DB 3DH ;'7'的接通键码
DB 45H ;'0'的接通键码
DB 1EH ;'2'的接通键码
DB 2EH ;'5'的接通键码
DB 3EH ;'8'的接通键码
DB 66H ;'Back'的接通键码
DB 26H ;'3'的接通键码
DB 36H ;'6'的接通键码
DB 46H ;'9'的接通键码
DB 5AH ;'Enter'的接通键码
DB 05H ;'F1'的接通键码
DB 06H ;'F2'的接通键码
DB 04H ;'F3'的接通键码
DB 0CH ;'F4'的接通键码
;子程序---发送1个字节,入口参数:A=字节数据, 出口参数:A=原字节数据
SEND_B: MOV 22H,A ;转存A
MOV C,KBCLK ;等待PC允许发送,即KBCLK、KBDAT均未被PC拉为低电平
JNC CANCEL
MOV C,KBDAT
JNC CANCEL
LCALL SLEEP
MOV C,P
CPL C ;重要! 因为PC接收是按奇校验方式进行校验的,即8位+P位=9位为奇
MOV 20H.0,C ;转存奇偶校验位
MOV R4,#08H
CLR C ;发起始位0
MOV KBDAT,C
CLR KBCLK
LCALL SLEEP
SETB KBCLK
LCALL SLEEP
MOV C,KBCLK ;每发完1位都检查KBCLK是否被拉低,被拉低则放弃
JNC CANCEL
LOOP_S: RRC A ;发8位数据位
MOV KBDAT,C
CLR KBCLK
LCALL SLEEP
SETB KBCLK
LCALL SLEEP
MOV C,KBCLK
JNC CANCEL
DJNZ R4,LOOP_S
MOV C,20H.0 ;发奇偶校验位
MOV KBDAT,C
CLR KBCLK
LCALL SLEEP
SETB KBCLK
LCALL SLEEP
MOV C,KBCLK
JNC CANCEL
SETB C ;发停止位1
MOV KBDAT,C
CLR KBCLK
LCALL SLEEP
SETB KBCLK
LCALL SLEEP ;发送完毕后KBCLK、KBDAT均保持高电平
CANCEL: MOV A,22H ;恢复A
RET
;子程序---接收1个字节,出口参数:A=字节数据
RECEV_B:CLR 20H.2
MOV R4,#08H
LOOP_R: CLR KBCLK ;接8位数据位
LCALL SLEEP
SETB KBCLK
LCALL SLEEP
MOV C,KBDAT
RRC A
MOV C,KBCLK ;每接收1位都检查KBCLK是否被拉低,被拉低则放弃
JNC SKIP
DJNZ R4,LOOP_R
CLR KBCLK ;接奇偶校验位
LCALL SLEEP
SETB KBCLK
LCALL SLEEP
MOV C,KBDAT
MOV 20H.1,C
MOV C,KBCLK
JNC SKIP
STOP: CLR KBCLK ;接停止位
LCALL SLEEP
SETB KBCLK
LCALL SLEEP
MOV C,KBCLK
JNC SKIP
MOV C,KBDAT
JNC STOP
CLR KBDAT ;拉低KBDAT(即应答位)以通知PC接收完毕
LCALL SLEEP
SETB KBDAT ;接收完毕后KBCLK、KBDAT均保持高电平
SETB KBCLK
SETB 20H.2
SKIP: NOP
RET
;子程序---键号转换并显示,入口参数:R7=键号
DISP: CLR C
MOV A,#15 ;判断是否为'F4'键
SUBB A,R7
JZ FUNC4
MOV A,#14 ;判断是否为'F3'键
SUBB A,R7
JZ FUNC3
MOV A,#13 ;判断是否为'F2'键
SUBB A,R7
JZ FUNC2
MOV A,#12 ;判断是否为'F1'键
SUBB A,R7
JZ FUNC1
MOV A,#11 ;判断是否为'Enter'键
SUBB A,R7
JZ ENTER
MOV A,#7 ;判断是否为'Back'键
SUBB A,R7
JZ BACK
MOV A,R6 ;如果是数字序列开始,先清除原功能键显示,数字滚动显示
JNZ NUM
ACALL LCD_CLR
NUM: MOV A,R7
MOV DPTR,#TAB_ASC
MOVC A,@A+DPTR ;取键号对应的ASCII码
ACALL LCD_DSP
INC R6 ;记录数字按键个数
MOV A,R7
MOV @R0,A ;数字键号存入缓冲区
INC R0 ;指向下一个缓冲区地址
SJMP RETURN
FUNC1: ACALL LCD_CLR
MOV A,#46H ;'F'的ASCII码
ACALL LCD_DSP
MOV A,#31H ;'1'的ASCII码
ACALL LCD_DSP
SJMP ORDER
FUNC2: ACALL LCD_CLR
MOV A,#46H ;'F'的ASCII码
ACALL LCD_DSP
MOV A,#32H ;'2'的ASCII码
ACALL LCD_DSP
SJMP ORDER
FUNC3: ACALL LCD_CLR
MOV A,#46H ;'F'的ASCII码
ACALL LCD_DSP
MOV A,#33H ;'1'的ASCII码
ACALL LCD_DSP
SJMP ORDER
FUNC4: ACALL LCD_CLR
MOV A,#46H ;'F'的ASCII码
ACALL LCD_DSP
MOV A,#34H ;'2'的ASCII码
ACALL LCD_DSP
SJMP ORDER
ENTER: ACALL LCD_CLR
MOV A,#45H ;'E'的ASCII码
ACALL LCD_DSP
MOV A,#6EH ;'n'的ASCII码
ACALL LCD_DSP
MOV A,#74H ;'t'的ASCII码
ACALL LCD_DSP
MOV A,#65H ;'e'的ASCII码
ACALL LCD_DSP
MOV A,#72H ;'r'的ASCII码
ACALL LCD_DSP
SJMP ORDER
BACK: ACALL LCD_CLR
MOV A,R6
JZ NONUM
MOV R0,#30H ;重置数字键存储缓冲区首址
DEC R6 ;去掉最后一个数字键
MOV A,R6
JZ NONUM
MOV R4,A ;置待重显数字键数目
RECALL: MOV A,@R0
MOV DPTR,#TAB_ASC
MOVC A,@A+DPTR ;取键号对应的ASCII码
ACALL LCD_DSP
INC R0
DJNZ R4,RECALL
SJMP RETURN
NONUM: MOV A,R7 ;无数字键可消退时显示一个光标块
MOV DPTR,#TAB_ASC
MOVC A,@A+DPTR ;取键号对应的ASCII码
ACALL LCD_DSP
SJMP RETURN
ORDER: MOV R6,#00H ;清除数字键已按次数
MOV R0,#30H ;重置数字键存储缓冲区首址
RETURN: RET
TAB_ASC1:DB 30H ;'0'的ASCII码
DB 31H ;'1'的ASCII码
DB 32H ;'2'的ASCII码
DB 33H ;'3'的ASCII码
DB 34H ;'4'的ASCII码
DB 35H ;'5'的ASCII码
DB 36H ;'6'的ASCII码
DB 37H ;'7'的ASCII码
DB 38H ;'8'的ASCII码
DB 39H ;'9'的ASCII码
TAB_ASC: DB 31H ;'1'的ASCII码
DB 34H ;'4'的ASCII码
DB 37H ;'7'的ASCII码
DB 30H ;'0'的ASCII码
DB 32H ;'2'的ASCII码
DB 35H ;'5'的ASCII码
DB 38H ;'8'的ASCII码
DB 0FFH ;'Back'的假借ASCII码
DB 33H ;'3'的ASCII码
DB 36H ;'6'的ASCII码
DB 39H ;'9'的ASCII码
;子程序---LCD显示字符,入口参数:A=字符的ASCII码
LCD_DSP:MOV DPTR,#8100H ;指定LCD数据口地址
MOVX @DPTR,A
ACALL F_BUSY
RET
;子程序---LCD显示清除,并设显示起始在第二行最末
LCD_CLR:MOV DPTR,#8000H ;指定LCD指令口地址
MOV A,#01H ;清屏并置AC为0
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#(0C0H+10H) ;设置DDRAM地址
MOVX @DPTR,A
ACALL F_BUSY
RET
LCD_SET_H:MOV DPTR,#8000H ;指定LCD指令口地址
MOV A,#38H ;功能设置,8位接口,双行显示,5X7点阵
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#0CH ;开显示,关光标,不闪烁
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#06H ;显示移位,AC为增量方式
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#(80H+00H) ;设置DDRAM地址,显示起始在第二行最末
MOVX @DPTR,A
ACALL F_BUSY
RET
LCD_SET_L:MOV DPTR,#8000H ;指定LCD指令口地址
MOV A,#38H ;功能设置,8位接口,双行显示,5X7点阵
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#0CH ;开显示,关光标,不闪烁
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#06H ;显示移位,AC为增量方式
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#(80H+01H) ;设置DDRAM地址,显示起始在第二行最末
MOVX @DPTR,A
ACALL F_BUSY
RET
;子程序---LCD初始化及功能设置
LCD_SET:MOV DPTR,#8000H ;指定LCD指令口地址
MOV A,#01H ;清屏并置AC为0
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#38H ;功能设置,8位接口,双行显示,5X7点阵
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#0CH ;开显示,关光标,不闪烁
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#07H ;显示移位,AC为增量方式
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#(0C0H+10H) ;设置DDRAM地址,显示起始在第二行最末
MOVX @DPTR,A
ACALL F_BUSY
RET
;子程序---LCD软件复位
LCD_RST:MOV DPTR,#8000H ;指定LCD指令口地址
LCALL DELAY20
MOV A,#30H
MOVX @DPTR,A
LCALL DELAY20
MOV A,#30H
MOVX @DPTR,A
LCALL DELAY20
MOV A,#30H
MOVX @DPTR,A
LCALL DELAY20
MOV A,#34H ;功能设置
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#04H ;关显示
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#01H ;清屏
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#06H ;设定输入方式
MOVX @DPTR,A
ACALL F_BUSY
RET
;子程序---判断LCD是否忙,并等待直至非忙状态
F_BUSY: PUSH DPH
PUSH DPL
PUSH PSW
PUSH A
MOV A,#0FFH
LOOP2: MOV DPTR,#8200H
MOVX A,@DPTR
JB ACC.7,LOOP2
POP A
POP PSW
POP DPL
POP DPH
RET
;子程序---延时100ms
DELAY100:MOV R4,#64H
DL4: ACALL DELAY1
DJNZ R4,DL4
RET
;子程序---延时20ms
DELAY20:MOV R3,#14H
DL3: ACALL DELAY1
DJNZ R3,DL3
RET
;子程序---延时1ms
DELAY1: MOV R1,#0AH
DL2: MOV R2,#18H
DL1: NOP
NOP
DJNZ R2,DL1
DJNZ R1,DL2
RET
;子程序---延时42us,用以形成12000b/s的KBCLK
SLEEP: MOV R2,#14H
DL5: DJNZ R2,DL5
RET
;编译到此前为止
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -