📄 19计算器.asm
字号:
PUB_SHORT_BCD1_A:
MOV A,@R0
SWAP A
ANL A,#0F0H
INC R0
MOV B,@R0
ANL B,#0FH
ORL A,B
MOV @R1,A
INC R0
INC R1
DEC KEY_LEN
DJNZ KEY_LEN,PUB_SHORT_BCD1_A
POP KEY_LEN
MOV A,KEY_LEN
JNB ACC.0,PUB_SHORT_BCD1_B
INC A ;是奇数则长度加1再除以2
PUB_SHORT_BCD1_B:
CLR C
RRC A ;转换后的长度为KEY_LEN除以2
MOV R7,A
RET
PUB_SHORT_BCD1_C:
POP KEY_LEN
MOV R7,#1
RET
;------------------------------------------
;将压缩BCD码转换为非压缩BCD码
;入口:
; R0 :压缩BCD码数据源地址(前256B)
; R7 :压缩BCD码长度
; KEY_BUF :非压缩BCD码目标地址(默认)
;出口: KEY_BUF KEY_LEN
;------------------------------------------
PUB_LONG_BCD:
MOV R1,#KEY_BUF
MOV A,R7
RL A
MOV KEY_LEN,A ;转换后的长度为R7乘以2
PUB_LONG_BCD1_A:
MOV A,@R0 ;取数
SWAP A
ANL A,#0FH
MOV @R1,A ;高位十进制数转换完毕
INC R1 ;目标地址加1
MOV A,@R0
ANL A,#0FH
MOV @R1,A ;低位十进制数转换完毕
INC R0 ;源地址加1
INC R1
DJNZ R7,PUB_LONG_BCD1_A
RET
;------------------------------------
;清除指定的RAM单元
;入口: R0:源地址 R7:长度
;------------------------------------
PUB_CLEAR_RAM1:
CJNE R7,#0,PUB_CLEAR_RAM1_1
SJMP PUB_CLEAR_RAM1_E
PUB_CLEAR_RAM1_1:
MOV @R0,#0
INC R0
DJNZ R7,PUB_CLEAR_RAM1_1
PUB_CLEAR_RAM1_E:
RET
;----------------------------------------
;在前256B内使源串数据右对齐到目标串
;R0:源串首地址 R1:目标串尾地址 R7:长度
;要求:R1>R0+R7
;------------------------------------------
PUB_MOV_RAM_R:
PUSH ACC
MOV A,R7
JZ PUB_MOV_RAM_R1A
MOV A,R0
ADD A,R7
DEC A
MOV R0,A
PUB_MOV_RAM_R1B:
MOV A,@R0
MOV @R1,A
DEC R0
DEC R1
DJNZ R7,PUB_MOV_RAM_R1B
PUB_MOV_RAM_R1A:
POP ACC
RET
;--------------------------------------
;前256B RAM空间数据串移动:
;入口: R0:源地址 R1:目标地址 R7:长度
;--------------------------------------
PUB_MOV_RAM11:
PUSH ACC
CJNE R7,#0,PUB_MOV_RAM11_0
SJMP PUB_MOV_RAM11_E
PUB_MOV_RAM11_0:
MOV A,@R0
MOV @R1,A
INC R0
INC R1
DJNZ R7,PUB_MOV_RAM11_0
PUB_MOV_RAM11_E:
POP ACC
RET
;--------------------------------
;发送一字节数据
;入口:ACC
;--------------------------------
LED_DISP_BYTE:
PUSH ACC
CLR LED_SCL
MOV R7,#8
LED_DISP_BYTE1:
RLC A
MOV LED_SDA,C
NOP
NOP
SETB LED_SCL
NOP
NOP
CLR LED_SCL
DJNZ R7,LED_DISP_BYTE1
POP ACC
RET
;---------------------------------------------
;右对齐显示LED_DIS_BUF缓冲区中的非压缩BCD数据
;入口: LED_DIS_BUF:起始地址
; DIS_LEN:显示长度
;----------------------------------------------
LED_DISP_DATA:
PUSH PSW
PUSH ACC
PUSH DPH
PUSH DPL
MOV PSW,#BANK2_REG
MOV A,#LED_DIS_BUF
ADD A,DIS_LEN
DEC A
MOV R0,A
MOV R6,DIS_LEN
MOV DPTR,#DIS_TAB
LED_DISP_DATA_A:
MOV A,@R0
ANL A,#0FH
MOVC A,@A+DPTR
LCALL LED_DISP_BYTE
DEC R0
DJNZ R6,LED_DISP_DATA_A
MOV A,#MAX_DATA_LEN
CLR C
SUBB A,DIS_LEN
JZ LED_DISP_DATA_END
MOV R6,A
MOV A,#0FFH
LED_DISP_DATA_B:
LCALL LED_DISP_BYTE
DJNZ R6,LED_DISP_DATA_B
LED_DISP_DATA_END:
POP DPL
POP DPH
POP ACC
POP PSW
RET
;------------------------------------
;清除LED上的显示内容
;------------------------------------
LED_CLR_FULL:
PUSH PSW
PUSH ACC
PUSH DPH
PUSH DPL
MOV PSW,#BANK2_REG
MOV R6,#6
LED_CLR_A:
MOV A,#0FFH
LCALL LED_DISP_BYTE
DJNZ R6,LED_CLR_A
POP DPL
POP DPH
POP ACC
POP PSW
RET
;----------------------------------------------------------------------
DIS_TAB: ;字形表
DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,88H,83H,0C6H,0A1H,86H,8EH,0FFH ;共阳极LED
DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H,00H ;共阴极LED
NOP9:
NOP
NOP
NOP
NOP
NOP
NOP
NOP
RET
;--------------------------------
;键盘扫描子程序
;键盘连接方式: P1.0-P1.3:KR1-KR4
; P1.4-P1.7:KC1-KC4
;入口: 无
;出口: A(所扫描到的逻辑键值K0-K12)
;使用: 第1组寄存器
;--------------------------------
KEY_SCAN:
PUSH PSW
PUSH DPH
PUSH DPL
MOV PSW,#BANK1_REG ;选择使用第1组寄存器(0-3)
;---------------------------------------
CLR K_DIGIT_FLAG
CLR K_CLR_FLAG
CLR K_DEL_FLAG
CLR K_ADD_FLAG
CLR K_SUB_FLAG
CLR K_ENT_FLAG
CLR K_ESC_FLAG
;---------------------------------------
KEY_SCAN_A:
ANL P1,#0FH ;P1口高4位置低,所有键的列线为低
MOV A,P1
ANL A,#KEY_ROW_MASK
XRL A,#KEY_ROW_MASK
JZ KEY_SCAN_A ;快速键判断
MOV KEY_COL,#0EFH
MOV R7,#KEY_COLS
KEY_SCAN_B:
ORL P1,#0F0H
MOV A,KEY_COL
ANL P1,A ;将列逐个设置为低
NOP
NOP
NOP
MOV A,P1 ;从低4位读进行值
ANL A,#KEY_ROW_MASK
MOV KEY_ROW,A
CJNE A,#KEY_ROW_MASK,KEY_SCAN_C
MOV A,KEY_COL
RL A
MOV KEY_COL,A
DJNZ R7,KEY_SCAN_B
LJMP KEY_SCAN_A
KEY_SCAN_C:
LCALL KEY_READ_DELAY
MOV A,P1 ;从低4位读进行值
ANL A,#KEY_ROW_MASK
XRL A,#KEY_ROW_MASK
JZ KEY_SCAN_A ;确定是否真的有键被按下
KEY_SCAN_C1:
MOV A,P1 ;从低4位读进行值
ANL A,#KEY_ROW_MASK
CJNE A,#KEY_ROW_MASK,KEY_SCAN_C1 ;是否键释放了
LCALL KEY_READ_DELAY
MOV A,P1
ANL A,#KEY_ROW_MASK
XRL A,#KEY_ROW_MASK
JNZ KEY_SCAN_C1
;-------------------------------------------------
MOV R3,#0 ;R3用于计算行值
MOV R2,#KEY_ROWS ;检测行值的循环次数
MOV A,KEY_ROW
KEY_SCAN_D1:
RRC A
JNC KEY_SCAN_D2 ;行值不为零则使行值加上1
INC R3 ;计算行值
DJNZ R2,KEY_SCAN_D1
KEY_SCAN_D2:
MOV R4,#0 ;R4用于计算列值
MOV R2,#KEY_COLS
MOV A,KEY_COL
SWAP A
KEY_SCAN_D3:
RRC A
JNC KEY_SCAN_D4
INC R4 ;计算列值
DJNZ R2,KEY_SCAN_D3
KEY_SCAN_D4:
MOV A,R3
RL A
RL A ;列值左移2次
ORL A,R4 ;取出行值与列值相或
;---------------------------------------------------
MOV DPTR,#KEY_VAL_TAB
MOVC A,@A+DPTR ;把物理键值变成逻辑键值
MOV R0,A ;保存键值
RL A
RL A ;乘以4
MOV DPTR,#KEY_SET_FLAG
JMP @A+DPTR
KEY_SET_FLAG:
SETB K_DIGIT_FLAG
SJMP KEY_SCAN_END ;0
;-----------------------------------------------------
SETB K_DIGIT_FLAG
SJMP KEY_SCAN_END ;1
;-----------------------------------------------------
SETB K_DIGIT_FLAG
SJMP KEY_SCAN_END ;2
;-----------------------------------------------------
SETB K_DIGIT_FLAG
SJMP KEY_SCAN_END ;3
;-----------------------------------------------------
SETB K_DIGIT_FLAG
SJMP KEY_SCAN_END ;4
;-----------------------------------------------------
SETB K_DIGIT_FLAG
SJMP KEY_SCAN_END ;5
;-----------------------------------------------------
SETB K_DIGIT_FLAG
SJMP KEY_SCAN_END ;6
;-----------------------------------------------------
SETB K_DIGIT_FLAG
SJMP KEY_SCAN_END ;7
;-----------------------------------------------------
SETB K_DIGIT_FLAG
SJMP KEY_SCAN_END ;8
;-----------------------------------------------------
SETB K_DIGIT_FLAG
SJMP KEY_SCAN_END ;9
;-----------------------------------------------------
SETB K_CLR_FLAG
SJMP KEY_SCAN_END
;-----------------------------------------------------
SETB K_DEL_FLAG
SJMP KEY_SCAN_END
;-----------------------------------------------------
SETB K_ADD_FLAG
SJMP KEY_SCAN_END
;-----------------------------------------------------
SETB K_SUB_FLAG
SJMP KEY_SCAN_END
;-----------------------------------------------------
SETB K_ENT_FLAG
SJMP KEY_SCAN_END
;-----------------------------------------------------
SETB K_ESC_FLAG
KEY_SCAN_END:
MOV A,R0 ;ACC 键值返回
POP DPL
POP DPH
POP PSW
RET
;---------------------------------
KEY_VAL_TAB: ;键值表 当需要时可更改此表 实现不同的按键排列
DB K7
DB K8
DB K9
DB K_ESC
;---------------------------------
DB K4
DB K5
DB K6
DB K_CLR
;---------------------------------
DB K1
DB K2
DB K3
DB K_DEL
;---------------------------------
DB K0
DB K_ENT
DB K_ADD
DB K_SUB
;--------------------------------------------
;延时10MS消除按键抖动
;--------------------------------------------
KEY_READ_DELAY:
MOV A,#10
KEY_READ_DEY_A:
LCALL PUB_DELAY_1MS
DEC A
JNZ KEY_READ_DEY_A
RET
;--------------------------------------------
;延时1ms
;--------------------------------------------
PUB_DELAY_1MS:
PUSH ACC
CLR A
PD1_0:
NOP
INC A
CJNE A,#0E4H,PD1_0 ;#E4H = 228D
POP ACC
RET
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -