📄 success_wjx3.asm
字号:
MOV R4,A ;以上3条调整待扫描行
MOV P1,A ;逐行扫描,被扫描行送0
MOV A,P1 ;读回各列线电平
MOV R3,#04H ;R3作计数器,存被扫描行的待查列数
ANL A,#0F0H ;高4位为有效的列线电平
SWAP A ;移到低4位
NEXT: RRC A ;调整待查列
JNC FIND ;被查列为低电平,按键找到,转出
INC R7 ;未找到,键号加1
DJNZ R3,NEXT ;被扫描行的待查列未完,转回NEXT
DJNZ R1,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 ;显示键值
SJMP L1
RETURN:RET
L1: 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 3DH ;'7'的接通键码
DB 3EH ;'8'的接通键码
DB 46H ;'9'的接通键码
DB 05H ;'F1'的接通键码
DB 25H ;'4'的接通键码
DB 2EH ;'5'的接通键码
DB 36H ;'6'的接通键码
DB 06H ;'F2'的接通键码
DB 16H ;'1'的接通键码
DB 1EH ;'2'的接通键码
DB 26H ;'3'的接通键码
DB 04H ;'F3'的接通键码
DB 45H ;'0'的接通键码
DB 66H ;'BACK'的接通键码
DB 5AH ;'ENTER'的接通键码
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,#0FH ;判断是否为'F4'键
SUBB A,R7
JZ FUNC4
CLR C
MOV A,#0BH ;判断是否为'F3'键
SUBB A,R7
JZ FUNC3
CLR C
MOV A,#07H ;判断是否为'F2'键
SUBB A,R7
JZ FUNC2
CLR C
MOV A,#03H ;判断是否为'F1'键
SUBB A,R7
JZ FUNC1
CLR C
MOV A,#0EH ;判断是否为'Enter'键
SUBB A,R7
JNZ JMP1
AJMP ENTER
JMP1: CLR C
MOV A,#0DH ;判断是否为'Back'键
SUBB A,R7
JZ BACK
CLR C
MOV A,R6 ;如果是数字序列开始,先清除原功能键显示,数字滚动显示
JNZ NUM
ACALL LCD_CLR
NUM: LCALL SOUNDADD
LCALL TNUM
INC R6 ;记录数字按键个数
MOV A,R7
MOV @R0,A ;数字键号存入缓冲区
INC R0 ;指向下一个缓冲区地址
LJMP RETURN
FUNC1: LCALL SOUNDADD
MOV R2,#00H
SJMP ORDER
FUNC2: LCALL SOUNDADD
MOV R2,#00H
SJMP ORDER
FUNC3: LCALL SOUNDADD
MOV R2,#00H
SJMP ORDER
FUNC4: LCALL SOUNDADD
MOV R2,#00H
SJMP ORDER
ENTER: LCALL TENTER
SJMP ORDER
BACK: LCALL SOUNDADD
MOV R2,#00H
MOV A,R6
JZ NONUM
DEC R6 ;去掉最后一个数字键
MOV A,R6
JZ NONUM
LJMP RETURN
NONUM: NOP
ORDER: MOV R6,#00H ;清除数字键已按次数
MOV R0,#40H ;重置数字键存储缓冲区首址
LJMP RETURN
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 37H ;'7'的ASCII码
DB 38H ;'8'的ASCII码
DB 39H ;'9'的ASCII码
DB 0FFH ;'F1'的ASCII码
DB 34H ;'4'的ASCII码
DB 35H ;'5'的ASCII码
DB 36H ;'6'的ASCII码
DB 0FFH ;'F2'的假借ASCII码
DB 31H ;'1'的ASCII码
DB 32H ;'2'的ASCII码
DB 33H ;'3'的ASCII码
DB 0FFH ;'F3'
DB 30H ;'0'
;子程序---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+0CH) ;设置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+0DH) ;设置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 R4,#14H
DL3: ACALL DELAY1
DJNZ R4,DL3
RET
;子程序---延时1ms
DELAY1: MOV R3,#0AH
DL2: MOV R1,#18H
DL1: NOP
NOP
DJNZ R1,DL1
DJNZ R3,DL2
RET
;子程序---延时42us,用以形成12000b/s的KBCLK
SLEEP: MOV R1,#14H
DL5: DJNZ R1,DL5
RET
SOUNDADD:PUSH DPH
PUSH DPL
PUSH ACC
mov B,#08H
MOV A,R7
MUL AB
MOV P0,A
SETB P3.5
NOP
CLR P3.5
POP ACC
POP DPL
POP DPH
RET
LCD_SET2: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,#06 ;显示移位,AC为增量方式
MOVX @DPTR,A
ACALL F_BUSY
MOV A,#(0C0H+00H) ;设置DDRAM地址,显示起始在第二行最末
MOVX @DPTR,A
ACALL F_BUSY
RET
LCD_SET_T1: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+0EH) ;设置DDRAM地址,显示起始在第二行最末
MOVX @DPTR,A
ACALL F_BUSY
RET
LCD_SET_T2: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+0FH) ;设置DDRAM地址,显示起始在第二行最末
MOVX @DPTR,A
ACALL F_BUSY
RET
TNUM:MOV A,#09H ;判断按下的键是不是"2"
CLR C
SUBB A,R7
JZ T20
SJMP T21
T20:AJMP TWO
T21: MOV A,#0CH ;判断按下的键是不是"0"
CLR C
SUBB A,R7
JZ T0
MOV A,#01H ;判断按下的键是不是"8"
CLR C
SUBB A,R7
JZ T8
AJMP OVER ;都不是则置R2为“#00H”
TWO:MOV R2,#01H
AJMP OUT
T0:MOV A,R2
CLR C
SUBB A,#01H
JZ INCRE
MOV A,R2
CLR C
SUBB A,#02H
JZ INCRE
AJMP OVER
T8:MOV A,R2
CLR C
SUBB A,#03H
JZ INCRE
AJMP OVER
TENTER:MOV A,R2
CLR C
SUBB A,#04H
JZ SUCCE
ACALL SOUNDADD
SJMP OVER
SUCCE: MOV A,#90H
MOV P0,A
SETB P3.5
NOP
CLR P3.5
AJMP OVER
INCRE:INC R2
AJMP OUT
OVER:MOV R2,#00H
OUT: RET
;编译到此前为止
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -