?? 19計算器.asm
字號:
BANK0_REG EQU 00H ;選擇第0組寄存器
BANK1_REG EQU 08H ;選擇第1組寄存器
BANK2_REG EQU 10H ;選擇第2組寄存器
BANK3_REG EQU 18H ;選擇第3組寄存器
LED_MAX_BITS EQU 06H ;LED最大位數
MAX_DATA_LEN EQU 6 ;計算數字長度
;鍵盤按鍵值的定義
K0 EQU 00H
K1 EQU 01H
K2 EQU 02H
K3 EQU 03H
K4 EQU 04H
K5 EQU 05H
K6 EQU 06H
K7 EQU 07H
K8 EQU 08H
K9 EQU 09H
K_CLR EQU 0AH
K_DEL EQU 0BH
K_ADD EQU 0CH
K_SUB EQU 0DH
K_ENT EQU 0EH
K_ESC EQU 0FH
KEY_ROWS EQU 4 ;鍵盤行數
KEY_COLS EQU 4 ;鍵盤列數
KEY_ROW_MASK EQU 0FH ;行值屏蔽碼
;------------------------------------------------------------------------------
LED_SDA EQU P3.0
LED_SCL EQU P3.1
K_DIGIT_FLAG EQU 00H
K_CLR_FLAG EQU 01H
K_DEL_FLAG EQU 02H
K_ADD_FLAG EQU 03H
K_SUB_FLAG EQU 04H
K_ENT_FLAG EQU 05H
K_ESC_FLAG EQU 06H
FR_FLAG EQU 07H
KEY_ROW EQU 27H
KEY_COL EQU 28H
PUB1_LEN EQU 29H
PUB2_LEN EQU 2AH ;公共緩沖區2長度1B
KEY_LEN EQU 2BH ;鍵盤緩沖區長度 1B
DIS_LEN EQU 2BH
CAL_FLAG EQU 2CH
PUB1_BUF EQU 50H ;公共緩沖區1 16B
PUB2_BUF EQU 60H ;公共緩沖區2 16B
PUB3_BUF EQU 70H ;公共緩沖區3 16B
KEY_BUF EQU 80H ;鍵盤緩沖區 16B
LED_DIS_BUF EQU KEY_BUF
;-----------------------------------------------------------------
ORG 0000H
LJMP START
START:
CLR EA
MOV SP,#0DFH
MOV PSW,#BANK0_REG
MOV R0,#20H
MOV R7,#0DFH-20H
LCALL PUB_CLEAR_RAM1 ;清0RAM單元
MOV KEY_LEN,#1
LCALL LED_DISP_DATA ;顯示初始0
;-----------------------------------------------------------------
CAL_FUN:
MOV CAL_FLAG,#0 ;把計算標志清零
;-----------------------------------------------------------------
CAL_INPUT_NUM1:
LCALL KEY_GET_DATA ;調用數字輸入子程序
JB K_ADD_FLAG,CAL_NUM1_ADD
JB K_SUB_FLAG,CAL_NUM1_SUB
JB K_ENT_FLAG,CAL_NUM1_ENT
SJMP START
CAL_NUM1_ADD:
JNB FR_FLAG,CAL_NUM1_ADD_A
MOV A,CAL_FLAG
CJNE A,#0EH,CAL_NUM1_ADD_A
MOV R0,#PUB3_BUF ;將計算結果作為第一個操作數
MOV R1,#PUB1_BUF
MOV R7,#MAX_DATA_LEN/2
LCALL PUB_MOV_RAM11
MOV CAL_FLAG,#01H
SJMP CAL_INPUT_NUM2
CAL_NUM1_ADD_A:
MOV CAL_FLAG,#01H
SJMP CAL_NUM1_END
;----------------------------------------------
CAL_NUM1_SUB:
JNB FR_FLAG,CAL_NUM1_SUB_A
MOV A,CAL_FLAG
CJNE A,#0EH,CAL_NUM1_SUB_A
MOV R0,#PUB3_BUF ;將計算結果作為第一個操作數
MOV R1,#PUB1_BUF
MOV R7,#MAX_DATA_LEN/2
LCALL PUB_MOV_RAM11
MOV CAL_FLAG,#02H
SJMP CAL_INPUT_NUM2
CAL_NUM1_SUB_A:
MOV CAL_FLAG,#02H
SJMP CAL_NUM1_END
CAL_NUM1_ENT:
CAL_NUM1_END:
MOV R1,#PUB1_BUF
LCALL PUB_SHORT_BCD
;-----------------------------------------------------------------
CAL_INPUT_NUM2: ;輸入第二個數
LCALL KEY_GET_DATA ;調用數字輸入子程序
JB K_ADD_FLAG,CAL_NUM2_ADD
JB K_SUB_FLAG,CAL_NUM2_SUB
JB K_ENT_FLAG,CAL_NUM2_ENT
SJMP START
CAL_NUM2_ADD:
JNB FR_FLAG,CAL_NUM2_ADD_A ;判斷是否未輸入數字而直接按K_ADD鍵
MOV CAL_FLAG,#01H
SJMP CAL_INPUT_NUM2 ;若是,則修正計算標識 并重新輸入第二個數字
CAL_NUM2_ADD_A:
MOV R1,#PUB2_BUF
LCALL PUB_SHORT_BCD
LCALL CALCULATE
MOV R0,#PUB3_BUF ;將計算結果作為第一個操作數
MOV R1,#PUB1_BUF
MOV R7,#MAX_DATA_LEN/2
LCALL PUB_MOV_RAM11
MOV CAL_FLAG,#01H
SJMP CAL_INPUT_NUM2
;----------------------------------------------
CAL_NUM2_SUB:
JNB FR_FLAG,CAL_NUM2_SUB_A ;判斷是否未輸入數字而直接按K_SUB鍵
MOV CAL_FLAG,#02H
SJMP CAL_INPUT_NUM2 ;若是,則修正計算標識 并重新輸入第二個數字
CAL_NUM2_SUB_A:
MOV R1,#PUB2_BUF
LCALL PUB_SHORT_BCD
LCALL CALCULATE
MOV R0,#PUB3_BUF ;將計算結果作為第一個操作數
MOV R1,#PUB1_BUF
MOV R7,#MAX_DATA_LEN/2
LCALL PUB_MOV_RAM11
MOV CAL_FLAG,#02H
SJMP CAL_INPUT_NUM2
CAL_NUM2_ENT:
MOV R1,#PUB2_BUF
LCALL PUB_SHORT_BCD
LCALL CALCULATE
MOV CAL_FLAG,#0EH
LJMP CAL_INPUT_NUM1
;-----------------------------------------------------------------
;-------------------------------------------
;進行計算操作
;入口: PUB1_BUF 第一個操作數(3字節壓縮BCD)
; PUB2_BUF 第二個操作數(3字節壓縮BCD)
; CAL_FLAG 計算標識(01:加法/02:減法)
;出口: PUB3_BUF 計算結果(3字節壓縮BCD)
;-------------------------------------------
CALCULATE:
PUSH ACC
MOV A,CAL_FLAG
CJNE A,#01H,CALCULATE_SUB
LCALL FUN_ADDITION
JC CALCULATE_ERR
SJMP CALCULATE_DIS
CALCULATE_SUB:
LCALL FUN_SUBTRATION
JC CALCULATE_ERR
CALCULATE_DIS:
MOV R0,#PUB3_BUF
MOV R7,#MAX_DATA_LEN/2
LCALL PUB_LONG_BCD
MOV R0,#KEY_BUF
MOV R7,#MAX_DATA_LEN
CAL_D_R_A:
MOV A,@R0
JNZ CAL_D_R_B
INC R0
DJNZ R7,CAL_D_R_A
MOV KEY_LEN,#1
SJMP CAL_D_R_C
CAL_D_R_B:
MOV A,#MAX_DATA_LEN
MOV KEY_LEN,R7
MOV R1,#KEY_BUF
LCALL PUB_MOV_RAM11 ;去掉前導0
CAL_D_R_C:
LCALL LED_DISP_DATA
POP ACC
RET
CALCULATE_ERR:
MOV R0,#KEY_BUF
MOV @R0,#0EH
MOV KEY_LEN,#1
LCALL LED_DISP_DATA ;顯示'E'提示錯誤
CALCULATE_ERR_A:
LCALL KEY_SCAN ;等待按K_ESC鍵返回
JNB K_ESC_FLAG,CALCULATE_ERR_A
POP ACC
LJMP START
;-----------------------------------------------------------------
;數字串輸入程序
;最長6位整數
;出口: K_ESC_FLAG
; K_ENT_FLAG(KEY_BUF開始的6B右對齊左補0)
; K_ADD_FLAG
; K_SUB_FLAG
;------------------------------------------------------------------
KEY_GET_DATA:
SETB FR_FLAG ;初始化'有效數字'標志位
MOV R0,#KEY_BUF
MOV R7,#MAX_DATA_LEN
LCALL PUB_CLEAR_RAM1
MOV KEY_LEN,#0
KEY_G_D_SCAN:
LCALL KEY_SCAN
JB K_DIGIT_FLAG,KEY_G_D_DIG
JB K_DEL_FLAG,KEY_G_D_DEL
JB K_CLR_FLAG,KEY_G_D_CLR
JB K_ADD_FLAG,KEY_G_D_ADD
JB K_SUB_FLAG,KEY_G_D_SUB
JB K_ENT_FLAG,KEY_G_D_ENT
JNB K_ESC_FLAG,KEY_G_D_SCAN
LJMP KEY_G_D_EXIT ;ESC 鍵退出
;-----------------------------------------------------------
KEY_G_D_ADD:
LJMP KEY_G_D_RETURN
;-----------------------------------------------------------
KEY_G_D_SUB:
LJMP KEY_G_D_RETURN
;-----------------------------------------------------------
KEY_G_D_CLR:
SETB FR_FLAG ;初始化'有效數字'標志位
MOV R0,#KEY_BUF
MOV R7,#MAX_DATA_LEN
LCALL PUB_CLEAR_RAM1
MOV KEY_LEN,#1
LCALL LED_DISP_DATA
MOV KEY_LEN,#0
SJMP KEY_G_D_SCAN
;-----------------------------------------------------------
KEY_G_D_ENT:
MOV A,KEY_LEN
JZ KEY_G_D_SCAN
MOV A,CAL_FLAG
JZ KEY_G_D_SCAN
LJMP KEY_G_D_RETURN
;-----------------------------------------------------------
KEY_G_D_DEL:
MOV A,KEY_LEN
JZ KEY_G_D_CLR
DEC KEY_LEN ;整數部分的刪除
MOV A,#KEY_BUF
ADD A,KEY_LEN
MOV R0,A
MOV @R0,#0
MOV A,KEY_LEN
JZ KEY_G_D_CLR ;KEY_LEN=0 重新開始輸入過程
LJMP KEY_G_D_DISP
;-----------------------------------------------------------
KEY_G_D_DIG:
MOV B,A
MOV A,KEY_LEN
XRL A,#MAX_DATA_LEN ;已經輸入MAX_DATA_LEN位整數
JZ KEY_G_D_SCAN ;是,則不在響應輸入數字
JNB FR_FLAG,KEY_G_D_DIG_B ;已經輸入有效數字了嗎
MOV A,B
JZ KEY_G_D_DIG_A
CLR FR_FLAG
KEY_G_D_DIG_A:
MOV KEY_LEN,#0 ;未輸入有效數字 且當前鍵值為0
KEY_G_D_DIG_B:
MOV A,#KEY_BUF
ADD A,KEY_LEN
MOV R0,A
MOV @R0,B
INC KEY_LEN ;輸入的不是第一個有效數字
LJMP KEY_G_D_DISP
;-----------------------------------------------------------
KEY_G_D_RETURN:
MOV A,KEY_LEN
JZ KEY_G_D_EXIT ;未輸入任何數字,直接按ENTER的判斷
MOV R1,#KEY_BUF+MAX_DATA_LEN-1
MOV R0,#KEY_BUF
MOV R7,KEY_LEN
LCALL PUB_MOV_RAM_R ;右對齊
MOV R0,#KEY_BUF
MOV A,#MAX_DATA_LEN
CLR C
SUBB A,KEY_LEN
MOV R7,A
LCALL PUB_CLEAR_RAM1
;-----------------------------------------------------------
KEY_G_D_EXIT:
MOV KEY_LEN,#MAX_DATA_LEN
RET
KEY_G_D_DISP:
LCALL LED_DISP_DATA
LJMP KEY_G_D_SCAN
;---------------------------------------------------------------------------
;--------------------------------------------
;數字加子程序
;出口:C=1溢出
;--------------------------------------------
FUN_ADDITION:
PUSH DPH
PUSH DPL
MOV R0,#PUB1_BUF+MAX_DATA_LEN/2-1
MOV R1,#PUB2_BUF+MAX_DATA_LEN/2-1
MOV DPH,#PUB3_BUF+MAX_DATA_LEN/2-1
CLR C
MOV R7,#MAX_DATA_LEN/2
LOOPADD:
MOV A,@R1
ADDC A,@R0 ;兩數相加
DA A ;調整相加結果,并送到r0中
MOV DPL,R1
MOV R1,DPH
MOV @R1,A
MOV R1,DPL
DEC R0
DEC R1
DEC DPH
DJNZ R7,LOOPADD
POP DPL
POP DPH
RET
;--------------------------------------------
;12字節相減子程序
;借位標志C=1有借位
;--------------------------------------------
FUN_SUBTRATION:
PUSH DPH
PUSH DPL
MOV R0,#PUB1_BUF+MAX_DATA_LEN/2-1
MOV R1,#PUB2_BUF+MAX_DATA_LEN/2-1
MOV DPH,#PUB3_BUF+MAX_DATA_LEN/2-1
CLR C ;清除借位標志
MOV R7,#MAX_DATA_LEN/2
LOOPSUB:
MOV A,#9AH
SUBB A,@R1
ADD A,@R0
DA A
MOV DPL,R1
MOV R1,DPH
MOV @R1,A
MOV R1,DPL
CPL C
DEC R0
DEC R1
DEC DPH
DJNZ R7,LOOPSUB
POP DPL
POP DPH
RET
;----------------------------------
;非壓縮BCD轉換成壓縮BCD
;入口:
; KEY_BUF :源地址(默認)
; KEY_LEN :待轉換數據長度
; R1 :目標地址(前256B)
;出口:
; R7:目標數據長度
;----------------------------------
PUB_SHORT_BCD:
PUSH KEY_LEN
MOV R0,#KEY_BUF
MOV A,KEY_LEN
JNB ACC.0,PUB_SHORT_BCD1_A ;長度為偶數時跳至PUB_SHORT_BCD1_A
MOV A,@R0
ANL A,#0FH ;長度為奇數時先轉化第一字節
MOV @R1,A
INC R0
INC R1
DEC KEY_LEN
MOV A,KEY_LEN
JZ PUB_SHORT_BCD1_C
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -