基于单片机双字节简易计算器程序设计
;================= Const =============================== SysStack Equ 07h ;08H...1FH
Dark Equ 10H
;----------------- Hardware ---------------------------- DisSegPort Equ 0000H ;0:Light up
DisCSPort Equ 2000H ;1:Select
KeyOutPort Equ DisCSPort;Key Output Port ;KeyInout:p1.0,P.1..P1.3 ;0:Pressed
;------------------ Byte Units ------------------------- KeyGetF Bit 20H ;1:Get A New Key KeyPress Bit 21H ;1:Key Released SumPress Bit 22H ;1 +
SumPress1 Bit 23H
EqualPress Bit 24H ;1 =
DivPress Bit 25H ;1 /
DivPress1 Bit 26H
MulPress Bit 27H ;1 *
MulPress1 Bit 28H
SubbPress Bit 29H ;1 -
SubbPress1 Bit 31H
NegPress Bit 32H
NegPress1 Bit 33H ;+/-
NegPress2 Bit 34H
DataPress Bit 35H ;数字键
FuncPress Bit 36H ;运算功能键
Sign Bit 37H
KeyCode Equ 60H
DisBuf Equ 70H;..75H
DeciPos Equ 76H ;Bit=1:Show DeciPoint SumVa Equ 77H ;press func KEY,Memory the DATA ON dis
DivVa Equ 78H ;the same UP
MulVa Equ 79H ;the same UP
SubbVa Equ 85H ;the same UP
;=======================================================
Org 0000H
AJmp Main
;======================================================= Display: Mov R1,#00000001B ;R1=DisCS
Mov R0,#DisBuf ;DisBuf Pointer
DisLoop: Mov B,#0FFH
Mov A,DeciPos ;小数点?
Anl A,R1
Jz DisNext ;0没小数点
Clr B.7 ;1小数点
DisNext: Mov Dptr,#DisCSPort;Do Display CS
Mov A,R1
Movx @Dptr,A
Mov A,@R0 ;Get Dis Char
Mov Dptr,#DisTab
Movc A,@A+Dptr
Anl A,B
Mov Dptr,#DisSegPort;Use Table
Movx @Dptr,A ;Send to DisSeg Port
ACall Delay
Inc R0
Mov A,R1
RL A
Mov R1,A
Cjne R0,#DisBuf+6,DisLoop
Ret
;------------------------------------------------------- ; Char: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
; Code: 00H, 01H, 02H, 03H, 04H, 05H, 06H, 07H, 08H, 09H
DisTab: DB 0C0H,0F9H,0A4H,0B0H, 99H, 92H, 82H,0F8H, 80H, 90H
; Char: 'A', 'B', 'C', 'D', 'E', 'F', '10H' ; Code: + , - , * , / , = , ON/C ,Dark
DB 088H,0BFH,0c6H,0a1H, 86H, 8eH ,0FFH ;-------------------------------------------------------- Delay: Mov R2,#04h
Delay1: Mov R3,#0
Djnz R3,$
Djnz R2,Delay1
Ret
;------------------------------------------------------- InitDis: Mov DisBuf+0,#0
Mov DisBuf+1,#Dark
Mov DisBuf+2,#Dark
Mov DisBuf+3,#Dark
Mov DisBuf+4,#Dark
Mov DisBuf+5,#Dark
Mov DeciPos,#00000000B
Ret
;------------------------------------------------------
NegDis: Mov DisBuf+5,#0BH
Ret
;-------------------------------------------------------
ScanKey: Mov Dptr,#KeyOutPort
Mov A,#0
Movx @Dptr,A
Mov A,P1
Cpl A ;取反处理,以便用A进行是否全0判断.指令只可判断全0不可判断全1
ANl A,#0FH ;屏蔽掉无关位
Ret
;-----------------------------------------------------------------------
ReadKey: ACall ScanKey
Jnz ReadKey1 ;A为0时无按键,只要有一位为1即有按键
Clr KeyPress
ReadKeyQ: Ret
ReadKey1: Jb KeyPress,ReadKeyQ ; 键压着可以准确定位是哪个键压着,故返回
Mov R2,#11111110B ;
Mov R3,#0 ;准备扫描第一列
ReadKeyLp: Mov Dptr,#KeyOutPort
Mov A,R2 ;列扫描值,选则列输出,检测
Movx @Dptr,A
Mov A,#0
Jnb P1.0,ReadKeyOk
Mov A,#6
Jnb P1.1,ReadKeyOk
Mov A,#12
Jnb P1.2,ReadKeyOk
Mov A,#18
Jnb P1.3,ReadKeyOk
Inc R3
Mov A,R2
RL A
Mov R2,A
AJmp ReadKeyLp
ReadKeyOk: Add A,R3 ;加上列扫描值
Setb KeyGetF
Setb KeyPress
Mov Dptr,#KeyChgTab
Movc A,@A+Dptr
Mov KeyCode,A
Ret
;---------------------------------------------------------------- ; KeyCode
00H,01H,02H,03H,04H,05H,06H,07H,08H,09H,0AH,0BH,0CH,0DH,0EH,0FH,10H,11H,12H,13
H,14H,15H,16H,17H
; OldKey Spc, 0 ,Dot,Equ,+ ,M+ ,% , 1 , 2 ,3 ,? ,M- ,+/-, 4 , 5 ,6 , - ,MRC, C ,
7 ,8 , 9 , X , /
KeyChgTab: DB 10, 0 ,11 ,12 ,13 ,14 ,15 , 1 , 2 ,3 ,16 ,17, 18 , 4 , 5 ,6 , 19,20 ,21 ,
7 ,8 , 9 , 22,23
;------------------------------------------------------- InitKey: Clr KeyGetF
Ret
;-------------------------------------------------------- InitFunck: Clr SumPress
Clr EqualPress
Clr DivPress
Clr MulPress
Clr SubbPress
InitNeg: Clr NegPress1
Clr NegPress2
Ret
;-------------------------------------------------------- ;================================================================= ;执行运算
Final:
Jb SumPress1,AddA ;是否按下过加法键加法
Jb DivPress1,DivD
Jb MulPress1,MulM
Jb SubbPress1,SubbS
Ajmp MainLoop
;--------------------------------------------------------- AddA: Clr SumPress1 ;执行加法运算
ACall FromLED
Jnb NegPress,AddC1
Clr NegPress
Mov A,R6
Orl A,#10000000B
Mov R6,A
AddC1: ACall InitDis
ACall AddF ;调用加法子程序
ACall ToLED
Ret
;----------------------------------------------------------
DivD: Clr DivPress1 ;执行除法运算
ACall FromLED
Jnb NegPress,DivC1
Clr NegPress
Mov A,R6
Orl A,#10000000B
Mov R6,A
DivC1: ACall InitDis
ACall DivF
ACall ToLED
Ret
;--------------------------------------------------------------
; R6R7*R4R5=R2R3R6R7 MulM: Clr MulPress1
ACall FromLED
Jnb NegPress,MulC1
Clr NegPress
Mov A,R6
Orl A,#10000000B
Mov R6,A
MulC1: ACall InitDis
ACall MulF ;调用乖法子程序
Acall ToLED
Ret
;-----------------------------------------------------------------
; R4R5-R6R7=R6R7
SubbS: Clr SubbPress1
ACall FromLED
Jnb NegPress,SubbC1
Clr NegPress
Mov A,R6
Orl A,#10000000B
Mov R6,A
SubbC1: ACall InitDiS
ACall SubbF
ACall ToLED
Ret
;------------------------ ;R4R5*R6R7=R6R7
MulF: Mov A,R4 ;判断两数符号同或异
Xrl A,R6
Mov C,ACC.7
Mov Sign,C
Mov A,R4
Clr ACC.7
Mov R4,A
Mov A,R6
Clr ACC.7
Mov R6,A
Mov A,R7
Mov B,R5
MUL AB
XCH A,R7
Mov R2,B
Mov B,R4
MUL AB
Add A,R2
Mov R2,A
Clr A
Addc A,B
Mov R3,A
Mov A,R6
Mov B,R5
MUL AB
Add A,R2
Mov R2,A
Mov A,B
Addc A,R3
Mov R3,A
Clr A
Addc A,#00H
XCH A,R6
Mov B,R4
MUL AB
Add A,R3
Mov R3,A
Mov A,B
Addc A,R6
XCH A,R2
Mov R6,A
Clr OV
Mov A,R6
Mov C,Sign
Mov ACC.7,C
Mov R6,A BackMul: Ret
;------------------------ ;R4R5/R6R7=R6R7 先R0R1 余R2R3
DivF: MOV A,R4
XRL A,R6
MOV C,ACC.7
MOV Sign,C
MOV A,R4
CLR ACC.7
MOV R4,A
MOV A,R6
CLR ACC.7
MOV R6,A
Mov R0,#0
Mov R1,#0 ;商赋初值零 Div2Byte_1:Mov A,R5
Clr c
Subb A,R7 ;低字节相减
Mov R5,A
Mov A,R4
Subb A,R6 ;高位相减
Mov R4,A
Jc Div2Byte_3 ;如果高字节都需要借位则退出循环
Clr c
Mov A,R1 ;R1自增
AddC A,#1
Mov R1,A
Jnc Div2Byte_2
Inc R0 ;商加一
Div2Byte_2:Sjmp Div2Byte_1 Div2Byte_3:Mov A,R0
Mov R6,A
Mov A,R1
Mov R7,A
MOV A,R6
JB ACC.7,IDIVE
JB OV,IDIVE
MOV C,Sign
MOV ACC.7,C
MOV R6,A
RET
IDIVE: SETB OV
BackDiv: Ret
;-----------------------------------------------------------------------------
AddF: MOV A,R4
MOV C,ACC.7
MOV Sign,C
XRL A,R6 ; 判断R3R6是否同号
MOV C,ACC.7
MOV A,R4
Clr ACC.7
MOV R4,A
MOV A,R6
CLR ACC.7
MOV R6,A
JC DAB2
ACall Add1
MOV A,R6
JB ACC.7,DABE DAB1 : MOV C,Sign
MOv ACC.7,C
MOV R6,A
CLR OV
RET
DABE : SETB OV
RET
DAB2 : LCALL Subb1
MOV A,R6
JNB ACC.7,DAB1
ACALL Cmpt
CPL Sign
SJMP DAB1 BackA: Ret
;-----------------------------------------------------------------------------
SubbF: MOV A,R6
CPL ACC.7
MOV R6,A
MOV A,R4
MOV C,ACC.7
MOV Sign,C
XRL A,R6 ; 判断R3R6是否同号
MOV C,ACC.7
MOV A,R4
Clr ACC.7
MOV R4,A
MOV A,R6
CLR ACC.7
MOV R6,A
JC DAB2
ACall Add1
MOV A,R6
JB ACC.7,SDABE SDAB1: MOV C,Sign
MOv ACC.7,C
MOV R6,A
CLR OV
RET
SDABE: SETB OV
RET
SDAB2: ACall Subb1
MOV A,R6
JNB ACC.7,SDAB1
ACALL CMPT
CPL Sign
SJMP SDAB1 ;------------------------ Cmpt : MOV A,R7
CPL A
ADD A,#01H
MOV R7,A
MOV A,R6
CPL A
ADDC A,#00H
MOV R4,6
Ret
;----------------------------- ;R4R5+R6R7=R6R7
Add1: Clr C
Mov A,R5
Add A,R7
Mov R7,A
Mov A,R4
Addc A,R6
Mov R6,A
Ret
;------------------------
;R4R5-R6R7=R6R7
Subb1: Mov A,R5
Clr C
Subb A,R7
Mov R7,A
Mov A,R4
Subb A,R6
Mov R6,A
Ret
;------------------------
;=====================================================================
==
;从显示屏读出数
FromLED: Mov r0,#DisBuf+4 ReadLED1: Cjne @r0,#Dark,ReadLED2
Dec r0
cjne r0,#DisBuf+0,READLED1
ReadLED2: Mov R6,#0
Mov A,@r0
Mov R7,A
Cjne r0,#DisBuf+0,ReadLed3
Sjmp BackFLED
ReadLED3: ACall R6R7Mul10
Dec r0
Mov A,@r0
Acall AddDis
Cjne r0,#DisBuf+0,ReadLED3 BackFLED: Ret
;====================================================================
AddDis: Clr C
Addc A,R7
Mov R7,A
Jnc BackAD
INC R6
BackAD: Ret
;-----------------------------------------------------------------------
;R6R7:=R6R7*10
R6R7Mul10: Mov A,R7
Mov B,#10
Mul AB
Mov R7,A ;R7*10 高
Mov A,#10
Xch A,B ;B:=10, A:=B R7低
Xch A,R6 ;A:=R6
Mul AB
Add A,R6
Mov R6,A
Ret
;------------------------------------------------------- ;将数送显示
;============================ Display Number ===============================
;change R67 into @r0.DisBuf(5)
;By: Linjuan, improved by: Wu ChuiHong
;Improvements:
; 1. Much Faster, 2. Fewer Codes, 3. r6,r7,r5,r6,r7,Dptr Not used
;Every Exec Time=275 us for num=1 to 65535, Test on 25/9/1998 ;Change: a,b,r0,R0,r2 if more than 1 byte
;---------------------------------------------------------------------------
;If R6.7=1(Negtive!) then R6R7:=0-R6R7, DisBuf+5:'-' ToLED: Mov A,R6
Jnb ACC.7,Correct
Clr ACC.7
Mov R6,A
ACall NegDis
Correct: Mov R0,#DisBuf
LCall FilDisBuf
Word2DR01: Mov r2,#4 ;1 word needs only 4 loops W2DLoop: Mov a,r6
jz W2DByte ; need only do low byte
Mov b,#10 ; else divided by 10
div ab
Mov r6,a
Mov a,r7
anl a,#0f0h
orl a,b
swap a
Mov b,#10
div ab
swap a
Xch a,r7
anl a,#0fh
xch a,b
swap a
orl a,b
Mov b,#10
div ab
Mov @R0,b
Inc R0
Orl a,r7
Mov r7,a
djnz r2,W2DLoop
jnz W2DOut0
Ret
;------------------------------ W2DByteClr:Mov r2,#2
ACall ClrDisLp
SJmp W2DByteA ;------------------------------ W2DByte: Mov a,r7
W2DByteA: Mov b,#10
div ab
Mov @R0,b
jz W2DOut
Mov b,#10
div ab
Inc R0
Mov @R0,b
jz W2DOut
Inc R0
W2DOut0: Mov @R0,a W2DOut: Ret
;---------------------------------------------------------------------------
ClrDisBuf0:Mov r0,#DisBuf ClrDisBufA:Mov r2,#15 ClrDisLp: Mov @r0,#' '
Inc r0
Djnz r2,ClrDisLp
Ret
;---------------------------------------------------------------------------
FilDisBuf: Mov a,#'0' FilDisBufA:Mov r2,#5 FilDisBufr:Mov b,r0
ClrDisBufL:Mov @r0,a
Dec r0
Djnz r2,ClrDisBufL
Mov r0,b
Ret
;---------------------------------------------------------------
IndectNeg1: ;检测是否负数,是则置1标志位
Mov A,DisBuf+5
Cjne A,#Dark,SNeg1
Sjmp BackIN1
SNeg1: Setb NegPress1 BackIN1: Ret
;------------------------------------------------------------
IndectNeg2:
Mov A,DisBuf+5
Cjne A,#Dark,SNeg2
Sjmp BackIN2
SNeg2: Setb NegPress2 BackIN2: Ret
;---------------------------------------------------------
IndectF: Jnb SumPress,KeyData1 ;未按过+,则继续输入数据
ACall InitDis ;按过键,则先清屏
Clr SumPress ;+复位
Sjmp BackIF
KeyData1: Jnb MulPress,KeyData2 ;未按过*,则继续输入数据
ACall InitDis ;按过键,则先清屏
Clr MulPress
Sjmp BackIF
KeyData2: Jnb SubbPress,KeyData3 ;未按过*,则继续输入数据
ACall InitDis ;按过键,则先清屏
Clr SubbPress
Sjmp BackIF
KeyData3: Jnb DivPress,KeyData4 ;未按过/,则继续输入数据
ACall InitDis ;按过键,则先清屏
Clr DivPress
Sjmp BackIF
KeyData4: Jnb EqualPress,BackIF ;等号键位为0,则继续输入数据
Clr EqualPress ;为1这先复位为0并清屏
ACall InitDis
BackIF: Ret
;=======================================================
Main: Mov Sp,#SysStack
ACall InitDis
ACall InitKey
ACall InitFunck
MainLoop: ACall Display
ACall ReadKey
Jbc KeyGetF,DoKey
AJmp MainLoop
DoKey:
Mov A,KeyCode
Clr C
Subb A,#10
Jnc DoFuncKey ;字模大于等于10,跳到功能键
Setb DataPress
Acall IndectF ;检测功能键
Mov A,DisBuf+4 ;If Top DisNum=Dark?
Cjne A,#Dark,KeyNumQ
Mov A,DisBuf+1
Cjne A,#Dark,RLDIS
Mov A,DisBuf+0
Jz KeyNum1
RLDIS: Mov A,DeciPos ;Left shift DeciP
RL A
Mov DeciPos,A
Mov DisBuf+4,DisBuf+3 ;Key=Number Key
Mov DisBuf+3,DisBuf+2
Mov DisBuf+2,DisBuf+1
Mov DisBuf+1,DisBuf+0 KeyNum1: Mov DisBuf+0,KeyCode
KeyNumQ: AJmp MainLoop
;-------------------------------------------------------
DoFuncKey: Mov Dptr,#JmpTab
Rl A ;叠加指令字节,防止跳到指令之间的空白区
Jmp @A+Dptr ; ?
JmpTab: AJmp Func0 ;A=0,Key=Clear
AJmp Func1 ;A=1,Key=Decimal Point
AJmp Func2 ;A=2,Key= =
AJmp Func3 ;A=3,Key=+
AJmp Func4 ;A=4,Key=
AJmp Func5 ;A=5,Key=
AJmp Func6 ;A=6,Key=
AJmp Func7 ;A=7,Key=
AJmp Func8 ;A=8,Key=
AJmp Func9 ;A=9,Key=
AJmp Func10 ;A=10,Key=
AJmp Func11 ;A=11,Key=
AJmp Func12 ;A=12,Key=
AJmp Func13 ;A=13,Key=
AJmp MainLoop
;------------------------------------------------------- Func0: ACall InitDis ;Clear
AJmp MainLoop
;------------------------------------------------------- Func1: Mov A,DeciPos
Jnz Func1Q ;DeciP Exist, Quit
Mov DeciPos,#00000001B ;Show DeciPoint Func1Q: AJmp MainLoop
;------------------------------------------------------- Func2: ACall IndectNeg2 ;=
ACall Final
ACall InitNeg
Setb EqualPress
Func2Q: AJmp MainLoop
;------------------------------------------------------- Func3: ACall FromLED ;+
Mov A,R6
Mov R4,A
Mov A,R7
Mov R5,A
Jnb NegPress,Func31
Clr NegPress
Mov A,R4
Orl A,#10000000B
Mov R4,A
Func31: ACall IndectNeg1
Setb SumPress
Setb SumPress1
Func3Q: AJmp MainLoop
;------------------------------------------------------- Func4: AJmp MainLoop
Func5: AJmp MainLoop
Func6: AJmp MainLoop
Func7: AJmp MainLoop
;-------------------------------------------------------------- Func8: Jnb DataPress,Func8Q ;检测没按下数字键 +/-
ACall NegDis ; +/-
Setb NegPress
Func8Q: AJmp MainLoop
;--------------------------------------------------------------
Func9: ACall FromLED ;-
Mov A,R6
Mov R4,A
Mov A,R7
Mov R5,A
Jnb NegPress,Func91
Clr NegPress
Mov A,R4
Orl A,#10000000B
Mov R4,A
Func91: ACall IndectNeg1
Setb SubbPress
Setb SubbPress1 Func9Q: AJmp MainLoop
;-----------------------------------------------------------
Func10: AJmp MainLoop
Func11: AJmp MainLoop
;---------------------------------------------------------
Func12:
ACall FromLED ; *
Mov A,R6
Mov R4,A
Mov A,R7
Mov R5,A
Jnb NegPress,Func121
Clr NegPress
Mov A,R4
Orl A,#10000000B
Mov R4,A
Func121: ACall IndectNeg1
Setb MulPress
Setb MulPress1 Func12Q: AJmp MainLoop
;-------------------------------------------------------------
Func13:
ACall FromLED ; /
Mov A,R6
Mov R4,A
Mov A,R7
Mov R5,A
Jnb NegPress,Func131
Clr NegPress
Mov A,R4
Orl A,#10000000B
Mov R4,A
Func131: ACall IndectNeg1
Setb DivPress
Setb DivPress1
Func13Q: AJmp MainLoop
;=======================================================
;---------------------------------------------------------------------------
End