; 4function Calculator ( + - * / ) ; work on two digit numbers ; ; keyboard 4x4 on port2 ; 7Seg on port1 [& port3 for common pins] ; 19 December 2006 ; last update:20 December 2006 ; ; by Siavash Salemi [30yavash] ; for more information[download Proteus design] visit my Homepage ; http://www.8052.com/users/30yavash/ ;----------------------------*CONSTANTS*----------------------------- FLAG EQU 30H ; + - * / INPUTNUM EQU 31H INPUTKEY EQU 32H M1 EQU 34H ; just used in PackedBCD M2 EQU 35H ; just used in PackedBCD NUM1 EQU 40H ; is two digit in BCD NUM2 EQU 41H ; is two digit in BCD RESULTP EQU 42H ; just used for floating point numbers RESULTL EQU 43H ; low byte of result RESULTH EQU 44H ; high byte of result DIGITS EQU 46H ; number of digits on 7seg TEMP0 EQU 60H TEMP1 EQU 61H TEMP2 EQU 62H TEMP3 EQU 63H ;----------------------------*main*----------------------------- ORG 00H MOV M1,#0 MOV M2,#0 MOV FLAG,#0 MOV NUM1,#0 MOV NUM2,#0 MOV RESULTL,#0 MOV RESULTH,#0 MOV RESULTP,#0 CLR PSW.1 ; negative or positive number 0=>+ and 1=>- keyup: LCALL DisplayResult LCALL Keyboard CJNE A,#0FFH,keyup readkey: LCALL DisplayResult LCALL Keyboard CJNE A,#0FFH,keypressed SJMP readkey keypressed: MOV INPUTKEY,A LCALL GetKeyNum MOV INPUTNUM,A MOV R7,INPUTNUM CJNE R7,#0FH,notenter ;Enter LCALL Calculator LJMP keyup notenter: MOV R7,INPUTNUM CJNE R7,#0EH,notc ;ON/C MOV M1,#0 MOV M2,#0 MOV RESULTP,#0 MOV RESULTL,#0 MOV RESULTH,#0 CLR PSW.1 LCALL Clean7Seg LJMP keyup notc: MOV R7,INPUTNUM CJNE R7,#0AH,notadd ;+ MOV FLAG,#1 MOV M1,#0 MOV M2,#0 LJMP keyup notadd: MOV R7,INPUTNUM CJNE R7,#0BH,notsubb ;- MOV FLAG,#2 MOV M1,#0 MOV M2,#0 LJMP keyup notsubb: MOV R7,INPUTNUM CJNE R7,#0CH,notmul ;* MOV FLAG,#3 MOV M1,#0 MOV M2,#0 LJMP keyup notmul: MOV R7,INPUTNUM CJNE R7,#0DH,is_number ;/ MOV FLAG,#4 MOV M1,#0 MOV M2,#0 LJMP keyup is_number: MOV RESULTH,#0 MOV RESULTP,#0 CLR PSW.1 LCALL PackedBCD LJMP keyup ;----------------------------*PackedBCD*----------------------------- PackedBCD: MOV A,M2 CJNE A,#0,thirdnumber SJMP packnumbers thirdnumber: MOV M1,#0 MOV M2,#0 packnumbers: MOV A,INPUTNUM MOV M2,M1 MOV M1,A MOV A,M2 SWAP A ORL A,M1 MOV RESULTL,A MOV R7,FLAG CJNE R7,#0,nextnum MOV NUM1,A SJMP ret_packed nextnum: MOV NUM2,A ret_packed: RET ;----------------------------*Calculator*----------------------------- Calculator: MOV A,FLAG CJNE A,#1,dosub LCALL Addition SJMP ret_calculator dosub: CJNE A,#2,domul LCALL Subtraction SJMP ret_calculator domul: CJNE A,#3,dodiv LCALL Multiply SJMP ret_calculator dodiv: CJNE A,#4,ret_calculator LCALL Division ret_calculator: MOV FLAG,#0 MOV M1,#0 MOV M2,#0 MOV NUM1,#0 MOV NUM2,#0 RET ;----------------------------*Division*----------------------------- Division: MOV A,NUM1 ANL A,#0FH MOV R0,A MOV A,NUM1 ANL A,#0F0H SWAP A MOV R1,A MOV R2,#0 MOV R3,#0 MOV A,NUM2 CJNE A,#0,valid_division MOV RESULTL,#0CBH MOV RESULTH,#0ABH MOV RESULTP,#0 SJMP ret_division valid_division: ANL A,#0FH MOV R4,A MOV A,NUM2 ANL A,#0F0H SWAP A MOV R5,A MOV R6,#0 MOV R7,#0 LCALL BCDDiv ;real part of division MOV RESULTL,A ;remainder*100 MOV R2,0H ; MOV R2,R0 MOV R3,1H ; MOV R2,R1 MOV R1,#0 MOV R0,#0 LCALL BCDDiv ;floating part of division MOV RESULTP,A MOV RESULTH,#0 ret_division: CLR PSW.1 ; positive number RET ;--------------------------------------------------------- ;(R3R2R1R0)/(R7R6R5R4) ; remainder:R3R2R1R0 ; quotient:A BCDDiv: MOV B,#0 mainpart: INC B CLR C MOV TEMP0,R0 ;save a copy MOV TEMP1,R1 ;save a copy MOV TEMP2,R2 ;save a copy MOV TEMP3,R3 ;save a copy MOV A,R0 SUBB A,R4 JNC nocarry1 ADD A,#10 nocarry1: MOV R0,A MOV A,R1 SUBB A,R5 JNC nocarry2 ADD A,#10 nocarry2: MOV R1,A MOV A,R2 SUBB A,R6 JNC nocarry3 ADD A,#10 nocarry3: MOV R2,A MOV A,R3 SUBB A,R7 MOV R3,A JNC mainpart ;quotient DEC B MOV A,B LCALL ConvertDEC2BCD ; A in BCD and B in DEC ;remainder MOV R0,TEMP0 MOV R1,TEMP1 MOV R2,TEMP2 MOV R3,TEMP3 RET ;----------------------------*Subtraction*----------------------------- Subtraction: CLR C MOV A,NUM1 LCALL ConvertBCD2DEC MOV TEMP1,A MOV A,NUM2 LCALL ConvertBCD2DEC MOV TEMP2,A MOV A,TEMP1 SUBB A,TEMP2 JNC subresult CPL A ADD A,#1 SETB PSW.1 subresult: LCALL ConvertDEC2BCD MOV RESULTL,A MOV RESULTP,#0 MOV RESULTH,#0 RET ;----------------------------*ConvertDEC2BCD*----------------------------- ConvertDEC2BCD: MOV B,#10 DIV AB SWAP A ORL A,B RET ;----------------------------*ConvertBCD2DEC*----------------------------- ConvertBCD2DEC: MOV TEMP0,A ;copy ANL A,#0F0H SWAP A MOV R1,A MOV A,TEMP0 ANL A,#0FH MOV R0,A MOV B,#10 MOV A,R1 MUL AB ADD A,R0 RET ;----------------------------*Addition*----------------------------- Addition: MOV A,NUM1 ADD A,NUM2 DA A JNC lowbyte MOV RESULTH,#1 lowbyte: MOV RESULTL,A CLR PSW.1 ; negative or positive number MOV RESULTP,#0H RET ;----------------------------*Multiply*----------------------------- Multiply: MOV A,NUM1 ANL A,#0F0H SWAP A MOV R1,A MOV A,NUM1 ANL A,#0FH MOV R0,A MOV A,NUM2 ANL A,#0F0H SWAP A MOV R3,A MOV A,NUM2 ANL A,#0FH MOV R2,A LCALL BCDMul MOV RESULTL,R4 MOV A,R5 SWAP A ORL RESULTL,A MOV RESULTH,R6 MOV A,R7 SWAP A ORL RESULTH,A CLR PSW.1 ; negative or positive number MOV RESULTP,#0 RET ;--------------------------------------------------------- ;(R1R0)*(R3R2)=R7R6R5R4 BCDMul: ;R4=R0R2 MOV A,R0 MOV B,R2 MUL AB MOV B,#10 DIV AB MOV R4,B MOV 60H,A ;c1 ;R5=R1R2+c1+R3R0 ;part 1 ;R5=R1R2+c1 MOV A,R1 MOV B,R2 MUL AB ADD A,60H MOV R5,A ;part2 ;R5+=R3R0 MOV A,R3 MOV B,R0 MUL AB ADD A,R5 MOV B,#10 DIV AB MOV R5,B MOV 60H,A ;c2 ;R6=R3R1+c2 ;R7=c3 MOV A,R3 MOV B,R1 MUL AB ADD A,60H MOV B,#10 DIV AB MOV R7,A ;c3 MOV R6,B RET ;----------------------------*DisplayResult*----------------------------- DisplayResult: MOV R0,#RESULTP MOV R1,#3 pushit: MOV A,@R0 ANL A,#0FH PUSH 0E0H ; PUSH A MOV A,@R0 ANL A,#0F0H SWAP A PUSH 0E0H ; PUSH A INC R0 DJNZ R1,pushit ;remove start zero MOV R1,#0 searchbits: MOV A,R1 CJNE A,#4,compare0 DEC R1 SJMP no0found compare0: POP B ;POP B MOV A,B CJNE A,#0,no0found INC R1 SJMP searchbits no0found: PUSH B ; PUSH A CLR C MOV A,#6 SUBB A,R1 MOV DIGITS,A MOV A,RESULTP CJNE A,#0,write_floating_result JB PSW.1,write_negative_result SJMP write_normal_result write_normal_result: MOV A,DIGITS SUBB A,#2 MOV DIGITS,A MOV B,#11110111B ; select 7seg repeat_normal_result: POP 0E0H ; POP A XCH A,B RL A MOV P3,A XCH A,B LCALL BcdTo7Seg MOV P1,A LCALL ShortDelay DJNZ DIGITS,repeat_normal_result ;clear stack POP 0E0H ; POP A POP 0E0H ; POP A SJMP ret_displayresult write_negative_result: MOV A,DIGITS SUBB A,#2 MOV DIGITS,A MOV P3,#11101111B MOV P1,#40H LCALL ShortDelay MOV B,#11101111B ; select 7seg repeat_negative_result: POP 0E0H ; POP A XCH A,B RL A MOV P3,A XCH A,B LCALL BcdTo7Seg MOV P1,A LCALL ShortDelay DJNZ DIGITS,repeat_negative_result ;clear stack POP 0E0H ; POP A POP 0E0H ; POP A SJMP ret_displayresult write_floating_result: MOV A,DIGITS SUBB A,#2 MOV R6,A ;location of point MOV R5,#0 MOV B,#11110111B ; select 7seg repeat_floating_result: MOV R4,#00000000B INC R5 MOV A,R5 CJNE A,06H,popit MOV R4,#10000000B popit: POP 0E0H ; POP A XCH A,B RL A MOV P3,A XCH A,B LCALL BcdTo7Seg ORL A,R4 MOV P1,A LCALL ShortDelay DJNZ DIGITS,repeat_floating_result ret_displayresult: RET ;----------------------------*Clean7Seg*----------------------------- Clean7Seg: MOV P3,#00001111B ; select all 7seg MOV P1,#0 MOV RESULTH,#0 MOV RESULTL,#0 MOV RESULTP,#0 RET ;----------------------------*Keyboard*----------------------------- Keyboard: MOV P2,#0F0H LCALL ShortDelay MOV A,P2 CJNE A,#0F0H,scanrows MOV A,#0FFH SJMP ret_keyboard scanrows: MOV R0,#4 MOV R1,#11101111B; p2.4 is first row so we should start [scan] from first. nextrow: MOV A,R1 RR A MOV R1,A MOV P2,A LCALL ShortDelay MOV A,P2 ANL A,#0F0H CJNE A,#0F0H,findcol DJNZ R0,nextrow MOV A,#0FFH SJMP ret_keyboard findcol: MOV R2,#0 nextcol: CLR C RLC A JNC calculate INC R2 SJMP nextcol calculate: CLR C MOV A,#4 SUBB A,R0 MOV B,#4 MUL AB ADD A,R2 ; r=4(row)+(col) ret_keyboard: RET ;----------------------------*ShortDelay*----------------------------- ShortDelay: MOV TEMP0,#20 shortloop: MOV TEMP1,#20 DJNZ TEMP1,$ DJNZ TEMP0,shortloop RET ;----------------------------*GetKeyNum*----------------------------- GetKeyNum: INC A MOVC A,@A+PC RET DB 7,8,9,0DH DB 4,5,6,0CH DB 1,2,3,0BH DB 0EH,0,0FH,0AH ;----------------------------*BcdTo7Seg*----------------------------- BcdTo7Seg: INC A MOVC A,@A+PC RET DB 3FH,06H,5BH,4FH,66H,6DH,7CH,07H,7FH,67H ;0-9 for display on 7seg DB 01111001B,01110000B,01011100B; Ero for print Eror END