📄 sucelev.asm
字号:
SAO10: JB TODAO,JIE1 ;如果通道数已经设定,则转至JIE1
MOV R3,A ;通道数没有设定,此次输入默认为通道数
CLR C
SUBB A,#8 ;对输入通道数进行范围检查
JC JIE13 ;小于8,认为输入正确
AJMP SAO0 ;否则认为输入错误,等待下一次输入
JIE13: SETB TODAO ;通道数已经设定,则置位,下面的输入用于其他目的
MOV A,#HUCH ;将通道数填充到缓冲单元
ADD A,#5
MOV R1,A
MOV A,R3
MOV @R1,A
LJMP SAO0 ;返回继续扫描
SAO0: ACALL SHOW ;调显示
AJMP SAO
JIE1: CJNE A,#10,JIE2 ;通道数已输入的条件下,检查此输入是高低标志位吗
JNB XIAN,JIE3 ;若数据输入标志位置位,表明刚才输入了高低限数值
MOV A,R6 ;输入的高低限数值进行非压缩BCD转化为二进制
MOV B,#100
MUL AB
MOV R6,A
MOV A,R5
MOV B,#10
MUL AB
ADD A,R6
ADD A,R4
MOV R3,A ;转化完成的二进制要先送到R3进行保护
JNB GADI2,JIE4
MOV A,#HILMT ;如果当前设置高限,则将高限存储单元赋予 A
SJMP JIE5
JIE4: MOV A,#LOLMT ;如果当前设置低限,则将高限存储单元赋予 A
JIE5: ADD A,@R1
MOV R0,A ;找到限值存储单元
MOV A,R3 ;将保护后的二进制数弹出
MOV @R0,A ;存储到相应限制单元中
CLR XIAN ;将数据输入标志位、个、十、百标志位清零
CLR GEW ;为下一次输入做准备
CLR SHI
CLR BAI
MOV R0,#HUCH ;等待另一个限值输入前,要将百、十、个位消隐
MOV @R0,#15
INC R0
MOV @R0,#15
INC R0
MOV @R0,#15
JIE3: SETB GADI1 ;将高低设置选择标志位1,表明选择过高低设置标志
CPL GADI2 ;高低设置选择标志位2取反,下一次设置另一个限值
MOV A,R1 ;找到显示缓冲单元
DEC A
MOV R0,A ;将显示缓冲单元赋予 R0
JNB GADI2,JIE6
MOV @R0,#14 ;要设置高限时显示 H
MOV A,#HILMT ;找到此路对应的高限值存储单元
ADD A,@R1
SJMP JIE7
JIE6: MOV @R0,#11 ;要设置低限时显示 L
MOV A,#LOLMT
ADD A,@R1 ;找到此路对应的低限值存储单元
JIE7: MOV R0,A
MOV A,@R0 ;将高(低)限值传递到A中
MOV R3,A
MOV A,#HUCH ;填缓冲单元,显示此路原先的高(低)限值
ADD A,#2
MOV R0,A
MOV A,R3
MOV B,#100 ;填缓冲单元前,要将原限值转化为非压缩BCD
DIV AB
CJNE A,#0,JIE20 ;若原限值的百位为零,则消隐
MOV @R0,#15
SJMP JIE21
JIE20: MOV @R0,A
JIE21: MOV A,B
MOV B,#10
DIV AB
DEC R0
MOV @R0,A ;原限值的十位
DEC R0
MOV @R0,B ;原限值的个位
LJMP SAO0 ;继续扫描键盘
JIE2: JNB GADI1,SAO0 ;如果没有选择高低限标识,则返回继续扫描
MOV R3,A ;已经选择高低限标志位,对输入数据进行保护
CLR C ;判断数据输入是否在合理范围之内
SUBB A,#10
JNC SAO0 ;若大于 9,表明输入有误,返回继续扫描
MOV A,R3 ;小于等于 9,输入正确
CLR XIAN ;先将输入数据标志位置零,等判断输入限值小于
JB GEW,JIE8 ;(等于)100时再置位
JIE10: MOV R4,A ;如果个位输入标志位为零,则将此数赋予个位
MOV R5,#0 ;十位,百位置零
MOV R6,#0
MOV R0,#HUCH ;填缓冲单元
MOV @R0,A
INC R0
MOV @R0,#15 ;十位,百位先消隐
INC R0
MOV @R0,#15
SETB XIAN ;置位数据输入标志位,个位标志位,表明有数据输入
SETB GEW
CLR SHI ;清十位,百位输入标志位
CLR BAI
LJMP SAO0 ;继续扫描
JIE8: JB SHI,JIE9 ;若个位已经置位,表明以前已有一个数输入,此次
MOV R3,A ; 数据赋予十位
MOV A,R4 ;以前输入的数现在作为百位
MOV R5,A
MOV A,R3 ;此次输入的数作为个位
MOV R4,A
MOV R6,#0 ;百位置零
MOV R0,#HUCH ;填充显示缓冲区
MOV @R0,A ;个位送入显示缓冲区首个单元
INC R0
MOV A,R5 ;十位送入显示缓冲区第二个单元
MOV @R0,A
INC R0
MOV @R0,#15 ;百位仍然消隐
SETB XIAN ;置位数据输入标志位、个位、十位标志位
SETB SHI
SETB GEW
CLR BAI
LJMP SAO0 ;继续扫描,等待百位或退出操作
JIE9: JB BAI,JIE10 ;十位已输入的条件下,此次输入赋予百位
MOV R3,A
MOV A,R5 ;以前的十位现在当作百位
MOV R6,A
MOV A,R4 ;以前的个位现在当作十位
MOV R5,A
MOV A,R3 ;此次输入的数当作个位
MOV R4,A
MOV R0,#HUCH ;填充缓冲单元
MOV @R0,A ;个位填缓冲区首个单元
INC R0
MOV A,R5 ;十位填第二个单元
MOV @R0,A
INC R0 ;百位填第三个单元
MOV A,R6
MOV @R0,A
MOV B,#100 ;非压缩BCD转化为二进制
MUL AB
JB OV,ERR ;乘机超过255,则显示有错
MOV R6,A
MOV A,R5
MOV B,#10
MUL AB
ADD A,R6 ;加上十位后,判断是否超过255,若超过,显示有错
JC ERR
ADD A,R4
JC ERR ;加上个位后,判断是否超过255,若超过,显示有错
MOV R3,A ;判断输入的三位数是否符合要求
CLR C
SUBB A,#100
JNC ERR ;超过100表明有错
JIE12: SETB XIAN ;不等于100,表明此次输入数值符合要求
SETB BAI ;输入正确,置相应标识位
SETB GEW
SETB SHI
LJMP SAO0 ;等待下一次输入
ERR: CLR GEW ;输入错误,清相应标识位
CLR SHI
CLR BAI
MOV R0,#HUCH ;输入越界,则提示有错误
MOV @R0,#17 ;显示'R'
INC R0
MOV @R0,#17 ;显示'R'
INC R0
MOV @R0,#18 ;显示'E'
MOV NUMN,#10
MOV TH0,#3CH ;开定时器,将'ERR'显示 1S
MOV TL0,#080H
SETB TR0
ERR1: MOV R3,NUMN
LCALL SHOW
CJNE R3,#0,ERR1 ;'ERR'显示1S后,将个、十、百位消隐
MOV R0,#HUCH
MOV @R0,#15
INC R0
MOV @R0,#15
INC R0
MOV @R0,#15
LJMP SAO0
TAB1: DB 7, 4, 8, 5, 9, 6, 10,11,1, 0, 2, 15, 3, 14, 12,13,16,16,16,16,16
;'0''1''2''3''4''5''6''7''8''9''A' 'B' 'C' 'D' 'E''F'
DB 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16
;其它键值均按16处理
;############################################################ 键盘设定子程序终
KINP: LCALL KAP ;扫描键子程序,
JNZ KP1
SETB PSW.5 ;置无键标志
RET
KP1: SETB RS0 ;由于上面用到R4,R5,R6.故更换工作区,保护原数值
LCALL DELY ;去抖
LCALL KAP ;再次扫描键盘
JNZ KP2 ;转识键码程序
SETB PSW.5 ;置无键标志
CLR RS0 ;将工作区切换到原来的 0 区
RET
KP2: CLR PSW.5 ;置有键操作标志
MOV R2,#0FEH ;逐列扫描初始值
MOV R4,#00H ;0列加数
KP4: MOV DPTR,#0FFDDH
MOV A,R2
MOVX @DPTR,A ;送列扫描信号
MOV DPTR,#0FFDEH
MOVX A,@DPTR ;回读行信号
JB ACC.0,L1 ;不是第一行,转第二行
MOV A,#00H ;是第一行,行吗=0
AJMP KP5
L1: JB ACC.1,L2 ; 不是第二行,转第三行
MOV A,#08H ;是第二行,行码=8
AJMP KP5
L2: JB ACC.2,L3 ;不是第三行,转第四行
MOV A,#10H ;是第三行,行码=16
AJMP KP5
L3: JB ACC.3,NEXT ;不是第四行,转下一列
MOV A,#18H ;是第四行,行码=24
KP5: ADD A,R4 ;对应的行码+对应的列码=键码
PUSH ACC ;保护已经得到的键码
KP3: LCALL DELY
LCALL KAP ;继续扫描
JNZ KP3 ;A值不等于0,表示手未松开!
POP ACC ;A值等于0,手已经松开,弹回键码!
CLR RS0 ;将工作区切换到原来的 0 区
RET
NEXT: INC R4 ;下一列列码加1
MOV A,R2
JNB ACC.7,KINP ;列到最后列了吗?
RL A
MOV R2,A ;下一列
AJMP KP4 ;扫描下一列
KAP: MOV A,#00H ;全扫描字(列)
MOV DPTR,#0FFDDH
MOVX @DPTR,A ;送全扫描字
MOV DPTR,#0FFDEH
MOVX A,@DPTR ;回读行信息
CPL A
ANL A,#0FH ;得到A值,=0,无键;≠0,有键
RET
DELY: MOV R6,#14H ;去抖!
DL: MOV R7,#0FFH
DJNZ R7,$
DJNZ R6,DL
RET
;############################################################ 键盘扫描子程序终
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -