Project Weekly Progress Report
Project Title:
Microcontroller Implementation of a Small Robot Arm Controller
Week of: April 11th, 2000
Engineers:
Megan Bern and Ritesh Patel
Advisor’s Signature: _________________
Grade: _______
=================================================================
Objective:
For the week of April 11th, 2000, the objectives were to improve the P controller and continue with the menu system.
Progress:
The P controller code was investigated and several bugs were found. There was a problem with the multiplication of (7/4) of the filtered position signal. The number that was being multiplied by 7/4 was actually the initial position of the robot arm, which was zero degrees. The four cases for the summer were also rewritten. The code was then ran again.
The robot arm did not respond as desired. The signal driving the robot arm was saturating. The open loop path of the P controller was checked to see if there were any problems. This was done by disconnecting the feedback signal from the system. The robot arm moved with the joystick for a 360° range. This indicates that the open loop path of the P controller was working correctly.
The feedback path was then checked. This was done by disconnecting the signal that drives the robot arm from the system. The feedback signal was then evaluated at the point where it is feed into the summer as the robot arm was manually moved around in a 360° circle. The feedback signal was as predicted. When the robot arm was at 0° , the feedback signal measured as 0V. As the robot arm was moved from 0° to 180° , the feedback signal moved from 0V to approximately 4.45V. This was also the response of the feedback signal when the robot arm was moved from 0° to -180° . This is expected due to the 2’s compliment of negative signals.
This means that there must be a problem with the summer of the P controller. This will be further investigated next week.
The menu system was also improved. The input branch of the menu system was expanded. This is shown in bold in the code that is attached to this report. The joystick section of the input branch has already been implemented. The user input command signals were the next to implement. After the user chooses to input their own signal, the following prompt will be displayed:
1 = Positive Degree
2 = Negative Degree
The microcontroller will only accept a 1 or 2. If a 1 is accepted the following prompt will be displayed:
1=10 2=20 3=30 4=40
5=50 0=other
The microcontroller will only accept a 1, 2, 3, 4, 5, or 0. If a 1-5 is entered, the robot arm will move to the degree of choice. If a 0 is accepted the following prompt will be displayed:
6=60 7=70
8=80 9=90
The microcontroller will only accept a 6, 7, 8, or 9. The robot arm will then move to the degree of choice.
If a 2 is accepted from the input signal prompt, the following prompt will be displayed:
-1=10 -2=20 -3=30
-4=40 -5=50 0=other
The microcontroller will only accept a 1, 2, 3, 4, 5, or 0. If a 1-5 is entered, the robot arm will move to the degree of choice. If a 0 is accepted the following prompt will be displayed:
-6=60 -7=70
-8=80 -9=90
The microcontroller will only accept a 6, 7, 8, or 9. The robot arm will then move to the degree of choice.
To actually move the robot arm to a specified position degree can be done by finding what voltage level of the robot arm corresponds to the desired degree of position. The desired voltage level is converted into a hexadecimal number. This hexadecimal number is then placed into the program for the specified degree of position. These value cannot be determined until we have completed the P controller and measure the voltage that corresponds to the desired degree of position.
;Ritesh Patel & Megan Bern
;Program1
;01/25/00
;generates 100Hz square wave
;A/D and D/A conversion
;Digital Filter [Yn=.25Rn + .25(Rn-1)+.50(Yn-1)]
;include(mod515)
$INCLUDE(mod515.a51)
;include(digital)
$INCLUDE(digital.a51)
STARD EQU 8000H ;start address for program
ORG stard
JMP SETUP
;Interrupt Jump Table
org stard+2BH ;TF2 + EXF2 interrupt
AJMP TMR2SRV ;Jump to timer 1 interrupt
;-----------------------------------------------------------------
TMR2SRV: ;timer 2 service every 5 ms
MOV a,#2 ;load ACC for channel 2
CALL ADCIN ;call converter subroutine
;value in ACC
MOV a,joy ;MOVE JOYSTICK CONDITION INTO a
JZ around2 ;Jump if zero
MOV a,#1 ;load ACC for channel 1
CALL ADCIN2 ;CALL CONVERTER SUBROUTINE
;VALUE IN acc
AJMP AROUND3 ;jump to call d/a out
around2: MOV A,isig ;move input signal condition into a
JNZ INPSIGA ;jump if user is choosing input position
JZ around1 ;jump around if user is not choosing input signal
INPSIGA: CALL INPSIG ;jump to input signal routine
AROUND3: CALL da_out ;write to D/A converter, Chn 2
around1: MOV a,Tmr_Half ;0.05 second timer move to acc
JZ around ;jump if zero
DEC a ;decrement acc
MOV Tmr_Half,a ;move acc to half second timer
around:
CPL p4.1 ;generate pulse
CLR TF2 ;clear interrupt flag
RETI
; ADCIN subroutine.
; Return ACC with the 8 bit A/D conversion from the channel selected by ACC.
; Grabs current robot arm position after P-to-A/D hardware.
ADCIN:
ANL A,#00000111B ; ONLY 8 CHANNELS
ANL ADCON,#11000000B ; MODE FOR A/D CONVERSION: SINGLE
ORL ADCON,A ; "OR" IN THE CHANNEL
MOV DAPR,#0 ; START CONV W/NO REF VOLTAGE
JB BSY,$ ; LOOP TILL CONVERTED
MOV acc,ADDAT ; ACC = CONVERSION
;LOOP is the code for the digital filter yn=0.25rn+0.25r(n-1)+0.50y(n-1).
LOOP: ;calculate 0.25Rn
mov IPAD,a
CLR C
MOV IP_1,IPAD ;MOVE Rn INTO Rn-1
MOV IPAD,a ;MOVE Rn INTO a
MOV b,#4h ;MOVE 4 INTO b
DIV ab ;DIVIDE Rn BY 4
MOV R7,b ;MOVE REMAINDER 1 INTO R7
MOV R2,a ;MOVE Rn(1/4) INTO R2
;calculate 0.25Rn-1
MOV a,IP_1 ;MOVE Rn-1 INTO a
MOV b,#4h ;MOVE 4 INTO b
DIV ab ;DIVIDE Rn-1 BY 4
MOV R3,a ;MOVE Rn-1(1/4) INTO R3
MOV a,b ;MOVE REMAINDER 2 INTO a
ADD a,R7 ;ADD REMAINDER 1 TO REMAINDER 2
CLR C ;CLEAR CARRY FLAG
MOV R7,a ;MOVE SUM OF REMAINDERS 1 AND 2 INTO R7
;calculate 0.50Yn-1
MOV OP_1,OP ;MOVE Yn INTO Yn-1
MOV a,OP_1 ;MOVE Yn-1 INTO a
MOV b,#2h ;MOVE 2 INTO b
DIV ab ;DIVIDE Yn-1 BY 2
MOV R4,a ;MOVE Yn-1(1/2) INTO R4
MOV a,b ;MOVE REMAINDER 3 INTO a
MOV b,#2h ;MOVE 2 INTO b
MUL ab ;MULTIPLY REMAINDER 3 BY 2
CLR C
ADD a,R7 ;ADD (2)REMAINDER 3 TO REMAINDERS 1 AND 2
MOV b,#4h ;MOVE 4 INTO b
DIV ab ;DIVIDE TOTAL REMAINDERS BY 4
;calculate Yn
CLR C ;CLEAR CARRY FLAG
ADD a,R2 ;ADD (1/4)Rn TO REMAINDERS
CLR C ;CLEAR CARRY FLAG
ADD a,R3 ;ADD (1/4)Rn-1 TO REMAINDERS AND (1/4)Rn
CLR C ;CLEAR CARRY FLAG
ADD a,R4 ;ADD (1/2)Yn-1 TO REMAINDERS, (1/4)Rn, AND (1/4)Rn-1
MOV R5,a ;MOVE TOTAL, Yn, INTO R5
MOV a,b ;MOVE REMAINDER OF TOTAL REMAINDERS INTO a
CLR C ;CLEAR CARRY FLAG
SUBB a,#2 ;SUBTRACT 2 FROM REMAINDER OF REMAINDERS
JC HERE ;JUMP HERE IF REMAINDER IS LESS THAN 0.5
JZ THERE ;JUMP THERE IF REMAINDER IS 0.5
JMP THERE ;JUMP THERE IF REMAINDER IS GREATER THAN 0.5
THERE: MOV a,R5 ;MOVE Yn INTO a
CLR C ;CLEAR CARRY FLAG
ADD a,#1 ;ADD 1 TO Yn
MOV OP,a ;MOVE TOTAL, Yn, INTO CURRENT OUTPUT
LJMP MULT ;Jump to MULT
HERE: CLR C ;CLEAR CARRY FLAG
MOV a,R5 ;MOVE Yn INTO a
MOV OP,a ;MOVE TOTAL, Yn, INTO CURRENT OUTPUT
LJMP MULT
;THIS FUNCTION SUBTRACTS 80H FROM Yn and saves it in R6. IT IS DIVIDED BY 30 AND SAVED IN MEMORY.
;It is also multiplied by 7/4 and added to the previous value saved in memory.
;subtracts 80h from Current output and keeps track of sign.
MULT: MOV a,OP
MOV b,#80h ;MOVE 80H INTO B
CLR C ;CLEAR CARRY
SUBB a,b ;SUBTRACT OP-80H
JNC MULTA ;JUMP TO MULT IF OP-80H IS POSITIVE NUMBER OR ZERO
CLR C ;CLEAR CARRY FLAG
MOV negf,#1h ;MOVE 1 INTO RAM LOCATION negf
CPL a ;COMPLIMENT (OP-80H)
MOV b,#1h ;MOVE 1 INTO b
CLR C ;CLEAR CARRY FLAG
ADD a,b ;ADD (OP-80H)'+1
MULTA: ;divides value by 30 and saves in R2.
MOV R6,a ;MOVE OP-80H OR (OP-80H)'+1 INTO R6
MOV b,#1Eh ;MOVE 30 INTO b
DIV ab ;DIVIDE OP-80H BY 30
MOV R2,a ;MOVE (OP-80H)/30 INTO R2
MOV a,b ;MOVE REMAINDER INTO a
CLR C ;CLEAR CARY FLAG
SUBB a,#0Eh ;SUBTRACT 14 FROM REMAINDER
JZ MULT2 ;JUMP IF ZERO
JC MULT2 ;JUMP IF NEGATIVE
MULT1: MOV a,R2 ;MOVE (OP-80H)/30 INTO a
CLR C ;CLEAR CARRY FLAG
ADD a,#1h ;ADD 1 TO (OP-80H)/30
MOV R2,a ;MOVE (OP-80H)/30 INTO R2
MULT2: ;divides value by 4 and saves in R3.
MOV a,R6 ;MOVE (OP-80) OR (OP-80H)'+1 INTO a
MOV b,#4h ;MOVE 4 INTO b
DIV ab ;DIVIDE (OP-80H)/4
MOV R3,a ;MOVE (OP-80H)/4 INTO R3
MOV a,b ;MOVE REMAINDER INTO a
CLR C ;CLEAR CARRY FLAG
SUBB a,#1h ;SUBTRACT 1 FROM REMAINDER
JZ MULT3A ;JUMP IS ZERO
JC MULT3A ;JUMP IF NEGATIVE
MULT3: MOV a,R3 ;MOVE (OP-80H)/4 INTO a
CLR C ;CLEAR CARRY FLAG
ADD a,#1h ;ADD 1 TO (OP-80H)/4
MOV R3,a ;MOVE (OP-80H)/4 INTO R3
AJMP MULT4 ;JUMP TO MULT4
MULT3A: MOV a,R3 ;MOVE (OP-80H)/4 INTO a
MULT4: ;multiplies value by 7 and then adds value to (op-80h)/30
MOV b,#7h ;MOVE 7 INTO b
CLR C ;CLEAR CARRY FLAG
MUL ab ;MULTIPLY (OP-80H)/4 BY 7
MOV b,R2 ;MOVE (OP-80H)/30 INTO b
CLR C ;CLEAR CARRY
ADD a,b ;ADD [(7(OP-80H)/4)+((OP-80H)/30)]
MOV R2,a ;MOV [(7(OP-80H)/4)+((OP-80H)/30)] INTO R2
CALL da_out1
RET
;THIS GRABS THE CURRENT JOYSTICK LOCATION.
ADCIN2: ANL A,#00000111B ; ONLY 8 CHANNELS
ANL ADCON,#11000000B ; MODE FOR A/D CONVERSION: SINGLE
ORL ADCON,A ; "OR" IN THE CHANNEL
MOV DAPR,#0 ; START CONV W/NO REF VOLTAGE
JB BSY,$ ; LOOP TILL CONVERTED
MOV acc,ADDAT ; ACC = CONVERSION
LJMP REM3
;THIS FUNCTION CHECKS TO SEE WHAT POSITION THE USER WOULD LIKE THE ROBOT ARM TO MOVE TO AND ACCEPTS
;THAT POSITION AS THE INPUT SIGNAL.
INPSIG: MOV a,isig
CJNE a,#1h,DEG20
MOV a,#86h
LJMP REM3
DEG20: CJNE a,#2h,DEG30
MOV a,#8Dh
LJMP REM3
DEG30: CJNE a,#3h,DEG40
MOV a,#94h
LJMP REM3
DEG40: CJNE a,#4h,DEG50
MOV a,#9Bh
LJMP REM3
DEG50: CJNE a,#5h,DEG60
MOV a,#0A2h
LJMP REM3
DEG60: CJNE a,#6h,DEG70
MOV a,#0A9h
LJMP REM3
DEG70: CJNE a,#7h,DEG80
MOV a,#0B0h
LJMP REM3
DEG80: CJNE a,#8h,DEG90
MOV a,#0B8h
LJMP REM3
DEG90: CJNE a,#9h,DEGN10
MOV a,#0BFh
LJMP REM3
DEGN10: CJNE a,#11h,DEGN20
MOV a,#78h
LJMP REM3
DEGN20: CJNE a,#12h,DEGN30
MOV a,#71h
LJMP REM3
DEGN30: CJNE a,#13h,DEGN40
MOV a,#6Ah
LJMP REM3
DEGN40: CJNE a,#14h,DEGN50
MOV a,#63h
LJMP REM3
DEGN50: CJNE a,#15h,DEGN60
MOV a,#5Ch
LJMP REM3
DEGN60: CJNE a,#16h,DEGN70
MOV a,#55h
LJMP REM3
DEGN70: CJNE a,#17h,DEGN80
MOV a,#4Eh
LJMP REM3
DEGN80: CJNE a,#18h,DEGN90
MOV a,#47h
LJMP REM3
DEGN90: CJNE a,#19h,INPSIGB
MOV a,#40h
LJMP REM3
INPSIGB: LJMP INPSIG
;THIS FUNCTION SUBTRACTS 80 FROM THE INPUT AND THEN PERFORMS THE SUMMATION OF THE P CONTROLLER.
REM3: ;subtracts 80h from the input signal. checks to see if neg or pos.
;keeps track of sign.
MOV b,#80h ;MOVE 80H INTO b
CLR C ;clear carry flag
SUBB a,b ;SUBTRACT (INPUT-80H)
JNC REM3A ;JUMP IF (INPUT-80H) IS NOT A NEGATIVE NUMBER
MOV negi,#1h ;MOVE 1 INTO RAM LOCATION negi
CPL a ;COMPLIMENT (INPUT-80H)
MOV b,#1h ;MOVE 1 INTO b
CLR C ;clear carry flag
ADD a,b ;ADD (INPUT-80H)'+1
REM3A: ;ckecks to see if input is neg or pos.
MOV R4,a ;MOVE (INPUT-80H) OR (INPUT-80H)'+1 INTO R4
MOV a,negi ;MOVE INPUT CONDITION INTO a
JZ REM3B ;JUMP IF INPUT SIGNAL POSITIVE
;input is neg and checks to see if feedback is neg or pos.
MOV a,negf ;MOVE FEEDBACK CONDITION INTO a
JZ STOP ;JUMP IF FEEDBACK CONDITION IS POSITIVE
;input and feedback are both neg. subtracts input from feedback.
MOV a,R2 ;MOVE {[7((OP-80H)'+1)/4]+[(OP-80H)'+1/30]} INTO a
MOV b,R4 ;MOVE (INPUT-80H)'+1 INTO b
CLR C ;clear carry flag
SUBB a,b ;SUBTRACT {[7((OP-80H)'+1)/4]+[((OP-80H)'+1)/30]} - [(INPUT-80H)'+1]
MOV negi,#0 ;RESET negi TO ZERO
MOV negf,#0 ;RESET negf TO ZERO
MOV b,#80h ;MOVE 80H INTO b
CLR C
ADD a,b ;ADD {{[7((OP-80H)'+1)/4]+[(OP-80H)'+1/30]} - [(INPUT-80H)'+1]} + 80H
RET
REM3B: ;input is pos and ckecks to see if feedback is neg or pos.
MOV a,negf ;MOVE FEEDBACK CONDITION INTO a
JNZ STOP1 ;JUMP IF FEEDBACK CONDITION IS NEGATIIVE
;input and feedback are both pos. subtracts feedback from input signal.
MOV a,R4 ;MOVE (INPUT-80H) INTO a
MOV b,R2 ;MOVE [7(OP-80H)/4 + (OP-80H)/3] INTO b
CLR C
SUBB a,b ;SUBTRACT {(INPUT-80H) - [7(OP-80H)/4 + (OP-80H)/3]}
MOV negi,#0 ;RESET negi TO ZERO
MOV negf,#0 ;RESET negf TO ZERO
MOV b,#80h ;MOVE 80H INTO b
CLR C
ADD a,b ;ADD {(INPUT-80H) - [7(OP-80H)/4 + (OP-80H)/3]} + 80H
RET
STOP: ;input is neg and feedback is pos.
MOV b,R2 ;MOVE {[7((OP-80H)'+1)/4]+[(OP-80H)'+1/30]} INTO a
MOV a,#0h ;MOVE 0H INTO a
CLR C
SUBB a,b ;SUBTRACT 0H - {[7((OP-80H)'+1)/4]+[(OP-80H)'+1/30]}
MOV b,R4 ;MOVE (INPUT-80H)'+1 INTO b
CLR C
SUBB a,b ;SUBTRACT 0H - {[7((OP-80H)'+1)/4]+[(OP-80H)'+1/30]} - [(INPUT-80H)'+1]
MOV negi,#0 ;RESET negi TO ZERO
MOV negf,#0 ;RESET negf TO ZERO
MOV b,#80h ;MOVE 80H INTO b
CLR C
ADD a,b ;ADD {0H - {[7((OP-80H)'+1)/4]+[(OP-80H)'+1/30]} - [(INPUT-80H)'+1]} +
;80H
RET
STOP1: ;input is pos and feedback is neg.
MOV a,R4 ;MOVE (INPUT-80H) INTO a
MOV b,R2 ;MOVE [7(OP-80H)/4 + (OP-80H)/3] INTO b
CLR C ;clear carry flag
ADD a,b ;SUBTRACT {(INPUT-80H) - [7(OP-80H)/4 + (OP-80H)/3]}
MOV negi,#0 ;RESET negi TO ZERO
MOV negf,#0 ;RESET negf TO ZERO
MOV b,#80h ;MOVE 80H INTO b
CLR C
ADD a,b ;ADD {(INPUT-80H) - [7(OP-80H)/4 + (OP-80H)/3]} + 80H
RET
; da_out subrountine
; write value in ACC to D/A channel specified below
da_out: MOV P2,#DA_0 ; point to D/A channel 2
MOVX @R1,a ; write data
RET
da_out1: MOV P2,#DA_2
MOVX @R1,a
RET
;***********************************************
;
; Intialization Code
;
;***********************************************
SETUP:
MOV IEN0,#0 ;Disable ALL INTS
MOV SP,#70H ;Initialize STACK
SETB P5.5 ;Do a reset
CLR P5.5 ;bring it low
SETB P5.0 ;make A16 of 128K Ram, high
SETB P5.2 ;disable EEPROM
CLR P5.1 ;new port 5.1 for D/A
;END 80535 Stuff
MOV R0,#7FH ;CLEAR 128 BYTES OF RAM
clr_ram: MOV @R0,#0
DJNZ R0,clr_ram
SETB T2CON.0 ; timer 2: 16 bit operation
SETB T2CON.4 ; and auto-reload mode
MOV TH2,#0EDH ; load timer 2 registers
MOV TL2,#0E4H
MOV CRCH,#0EDH ; load capture registers
MOV CRCL,#0E4H ; timer 2
SETB ET2 ;enable timer 2 ovf int
SETB EAL ; enable all interrupts
Digital:
MOV IPAD,#0 ;Initialize IPAD
MOV IP_1,#0 ;Initialize IP_1
MOV OP,#0 ;Initialize OP
MOV OP_1,#0 ;Initialize OP_1
MOV Tmr_Half,#10 ;Initialize Half second timer to 10
MOV joy,#0 ;INITIALIZE JOYSTICK CONSITION TO ZERO
MOV negi,#0 ;Initialize input condition to zero
MOV negf,#0 ;Initialize feedback condition to zero
MOV isig,#0 ;Initialize input signal condition to zero
Call LCDINIT ; initialize LCD
;THIS FUNCTION CREATES THE MAIN MENU SYSTEM ON THE LCD.
main:
MOV DPTR,#lcddata ; initialize pointer
MOV R0,#0 ; initialize character count
dislop: MOV a,Tmr_Half ;move half second timer to acc
JNZ dislop
MOV Tmr_Half,#10 ;move 100(dec)in to half second timer
MOV A,R0 ; copy to A
MOVC A,@A+DPTR
Call LCDOUT
INC R0
CJNE R0,#40,dislop ; finished?, then loop
looplcd: CALL KEYIN1 ;call keypad subroutine
CJNE A,#31h,next1 ;Key 1 pressed
MOV joy,#0h
MOV isig,#0h
JMP INPUT1 ;jump if equal
next1: CJNE A,#32h,looplcd ;compare to 2 and if not equal jump
JMP OUTPUT1 ;if equal jump to output
INPUT1: MOV DPTR,#lcddata1 ; initialize pointer
MOV R0,#0 ; initialize character count
dislop1: MOV a,Tmr_Half ;move half second timer to acc
JNZ dislop1
MOV Tmr_Half,#10 ;move 100(dec)in to half second timer
MOV A,R0 ; copy to A
MOVC A,@A+DPTR
Call LCDOUT
INC R0
CJNE R0,#34,dislop1 ; finished?, then loop
looplcd1: CALL KEYIN1 ;call keypad subroutine
CJNE A,#31h,next2 ;Key 1 pressed
MOV joy,#1h ;set joystick condition to 1
MOV isig,#0h
JMP main
next2: CJNE A,#32h,looplcd1 ;compare to 2 and if not equal jump
MOV joy,#0h ;set joystick condition to zero
MOV isig,#1h
MOV DPTR,#lcd1 ; initialize pointer
MOV R0,#0 ; initialize character count
dislop6: MOV a,Tmr_Half ;move half second timer to acc
JNZ dislop6
MOV Tmr_Half,#10 ;move 100(dec)in to half second timer
MOV A,R0 ; copy to A
MOVC A,@A+DPTR
Call LCDOUT
INC R0
CJNE R0,#41,dislop6 ; finished?, then loop
looplcd6: CALL KEYIN1 ;call keypad subroutine
CJNE A,#31h,next7 ;Key 1 pressed
JMP posdeg
next7: CJNE A,#32h,looplcd6 ;compare to 2 and if not equal jump
JMP negdeg
posdeg: MOV DPTR,#lcd2 ; initialize pointer
MOV R0,#0 ; initialize character count
dislop7: MOV a,Tmr_Half ;move half second timer to acc
JNZ dislop7
MOV Tmr_Half,#10 ;move 100(dec)in to half second timer
MOV A,R0 ; copy to A
MOVC A,@A+DPTR
Call LCDOUT
INC R0
CJNE R0,#34,dislop7 ; finished?, then loop
looplcd7: CALL KEYIN1 ;call keypad subroutine
CJNE A,#31h,next8 ;Key 1 pressed
MOV isig,#1h
LJMP main
next8: CJNE A,#32h,next9 ;compare to 2 and if not equal jump
MOV isig,#2h
LJMP main
next9: CJNE A,#33H,next10
MOV isig,#3h
LJMP main
next10: CJNE A,#34H,next11
MOV isig,#4h
LJMP main
next11: CJNE A,#35H,next12
MOV isig,#5h
LJMP main
next12: CJNE A,#30H,looplcd7
otherdeg: MOV DPTR,#lcd3 ; initialize pointer
MOV R0,#0 ; initialize character count
dislop8: MOV a,Tmr_Half ;move half second timer to acc
JNZ dislop8
MOV Tmr_Half,#10 ;move 100(dec)in to half second timer
MOV A,R0 ; copy to A
MOVC A,@A+DPTR
Call LCDOUT
INC R0
CJNE R0,#21,dislop8 ; finished?, then loop
looplcd8: CALL KEYIN1 ;call keypad subroutine
CJNE A,#36h,next13 ;Key 1 pressed
MOV isig,#6h
LJMP main
next13: CJNE A,#37h,next14 ;compare to 2 and if not equal jump
MOV isig,#7h
LJMP main
next14: CJNE A,#38H,next15
MOV isig,#8h
LJMP main
next15: CJNE A,#39H,looplcd8
MOV isig,#9h
LJMP main
negdeg: MOV DPTR,#lcd4 ; initialize pointer
MOV R0,#0 ; initialize character count
dislop9: MOV a,Tmr_Half ;move half second timer to acc
JNZ dislop9
MOV Tmr_Half,#10 ;move 100(dec)in to half second timer
MOV A,R0 ; copy to A
MOVC A,@A+DPTR
Call LCDOUT
INC R0
CJNE R0,#39,dislop9 ; finished?, then loop
looplcd9: CALL KEYIN1 ;call keypad subroutine
CJNE A,#31h,next16 ;Key 1 pressed
MOV isig,#11h
LJMP main
next16: CJNE A,#32h,next17 ;compare to 2 and if not equal jump
MOV isig,#12h
LJMP main
next17: CJNE A,#33H,next18
MOV isig,#13h
LJMP main
next18: CJNE A,#34H,next19
MOV isig,#14h
LJMP main
next19: CJNE A,#35H,next20
MOV isig,#15h
LJMP main
next20: CJNE A,#30H,looplcd9
otherdeg1: MOV DPTR,#lcd5 ; initialize pointer
MOV R0,#0 ; initialize character count
dislop10: MOV a,Tmr_Half ;move half second timer to acc
JNZ dislop10
MOV Tmr_Half,#10 ;move 100(dec)in to half second timer
MOV A,R0 ; copy to A
MOVC A,@A+DPTR
Call LCDOUT
INC R0
CJNE R0,#25,dislop10 ; finished?, then loop
looplcd10: CALL KEYIN1 ;call keypad subroutine
CJNE A,#36h,next21 ;Key 1 pressed
MOV isig,#16h
LJMP main
next21: CJNE A,#37h,next22 ;compare to 2 and if not equal jump
MOV isig,#17h
LJMP main
next22: CJNE A,#38H,next23
MOV isig,#18h
LJMP main
next23: CJNE A,#39H,looplcd10
MOV isig,#19h
JMP main
lcd1: db 1ah,31h,20h,3dh,20h,50h,6fh,73h,69h,74h,69h,76h,65h
db 20h,44h,65h,67h,72h,65h,65h
db 0ah,0dh,32h,20h,3dh,20h,4eh,65h,67h,61h,74h,69h
db 76h,65h,20h,44h,65h,67h,72h,65h,65h
RET
lcd2: db 1ah,31h,3dh,31h,30h,20h,32h,3dh,32h,30h,20h,33h,3dh
db 33h,30h,20h,34h,3dh,34h,30h,0ah,0dh,35h,3dh,35h,30h
db 20h,4fh,3dh,4fh,74h,68h,65h,72h
RET
lcd3: db 1ah,36h,3dh,36h,30h,20h,37h,3dh,37h,30h,0ah,0dh
db 38h,3dh,38h,30h,20h,39h,3dh,39h,30h
RET
lcd4: db 1ah,31h,3dh,2dh,31h,30h,20h,32h,3dh,2dh,32h,30h,20h
db 33h,3dh,2dh,33h,30h,0ah,0dh,34h,3dh,2dh,34h,30h,20h
db 35h,3dh,2dh,35h,30h,20h,4fh,3dh,4fh,74h,68h,65h,72h
RET
lcd5: db 1ah,36h,3dh,2dh,36h,30h,20h,37h,3dh,2dh,37h,30h,0ah
db 0dh,38h,3dh,2dh,38h,30h,20h,39h,3dh,2dh,39h,30h
RET
lcddata1: db 1ah,50h,72h,65h,73h,73h,20h,31h,20h,6fh,72h,20h,32h
db 0ah,0dh,31h,3dh,4ah,4fh,59h,53h,54h,49h,43h,4bh,20h
db 32h,3dh,49h,4eh,53h,49h,47h,20h
RET
lcddata: db 1ah,50h,72h,65h,73h,73h,20h,31h,20h,6fh,72h,20h
db 32h,0ah,0dh,31h,3dh,49h,6eh,20h,32h,3dh
db 4fh,75h,74h,20h,46h,6fh,72h,20h,4dh,65h,6eh,75h,73h
RET
KEYIN1: JNB IE1,KEYIN1 ; LOOP TILL KEY PRESSED
clr ie1
PUSH DPH
PUSH DPL ; SAVE DPTR
MOV DPTR,#KEYTABL ; POINT TO TRANSLATE TABLE
MOV P2,#KEYSEL ; POINT TO KEYPAD PORT
MOVX A,@R1 ; GET KEY FROM PORT
ANL A,#11111B ; ONLY 5 BITS
MOVC A,@A+DPTR ; TRANSLATE TO KEY FROM TABLE
POP DPL
POP DPH
RET
KEYTABL: DB '123C456D789EA0BF'
OUTPUT1: MOV DPTR,#output2 ; initialize pointer
MOV R0,#0 ; initialize character count
dislop2: MOV a,Tmr_Half ;move half second timer to acc
JNZ dislop2
MOV Tmr_Half,#10 ;move 100(dec)in to half second timer
MOV A,R0 ; copy to A
MOVC A,@A+DPTR
Call LCDOUT
INC R0
CJNE R0,#40,dislop2 ; finished?, then loop
looplcd2: CALL KEYIN1 ;call keypad subroutine
CJNE A,#31h,next3 ;Key 1 pressed
JMP error
next3: CJNE A,#32h,looplcd2 ;compare to 2 and if not equal jump
JMP other
error: JMP main
other: MOV DPTR,#output3 ; initialize pointer
MOV R0,#0 ; initialize character count
dislop3: MOV a,Tmr_Half ;move half second timer to acc
JNZ dislop3
MOV Tmr_Half,#10 ;move 100(dec)in to half second timer
MOV A,R0 ; copy to A
MOVC A,@A+DPTR
Call LCDOUT
INC R0
CJNE R0,#40,dislop3 ; finished?, then loop
looplcd3: CALL KEYIN1 ;call keypad subroutine
CJNE A,#31h,next4 ;Key 1 pressed
JMP final
next4: CJNE A,#32h,looplcd3 ;compare to 2 and if not equal jump
JMP other1
final: JMP main
other1: MOV DPTR,#output4 ; initialize pointer
MOV R0,#0 ; initialize character count
dislop4: MOV a,Tmr_Half ;move half second timer to acc
JNZ dislop4
MOV Tmr_Half,#10 ;move 100(dec)in to half second timer
MOV A,R0 ; copy to A
MOVC A,@A+DPTR
Call LCDOUT
INC R0
CJNE R0,#42,dislop4 ; finished?, then loop
looplcd4: CALL KEYIN1 ;call keypad subroutine
CJNE A,#31h,next5 ;Key 1 pressed
JMP filtered
next5: CJNE A,#32h,looplcd4 ;compare to 2 and if not equal jump
JMP other2
filtered: JMP main
other2: MOV DPTR,#output5 ; initialize pointer
MOV R0,#0 ; initialize character count
dislop5: MOV a,Tmr_Half ;move half second timer to acc
JNZ dislop5
MOV Tmr_Half,#10 ;move 100(dec)in to half second timer
MOV A,R0 ; copy to A
MOVC A,@A+DPTR
Call LCDOUT
INC R0
CJNE R0,#41,dislop5 ; finished?, then loop
looplcd5: CALL KEYIN1 ;call keypad subroutine
CJNE A,#31h,next6 ;Key 1 pressed
JMP command
next6: CJNE A,#32h,looplcd5 ;compare to 2 and if not equal jump
JMP other3
command: JMP main
other3: JMP main
output6: JMP output6
output2: db 1ah,50h,72h,65h,73h,73h,20h,31h,20h,46h,6fh,72h,20h
db 45h,72h,72h,6fh,72h,20h,0ah,0dh,6fh,72h
db 20h,32h,20h,46h,6fh,72h,20h,4fh,74h,68h,65h,72h,20h,53h
db 69h,67h,73h
RET
output3: db 1ah,50h,72h,65h,73h,73h,20h,31h,20h,46h,6fh,72h,20h
db 4fh,75h,74h,70h,75h,74h,0ah,0dh,6fh,72h,20h,32h,20h
db 46h,6fh,72h,20h,4fh,74h,68h,65h,72h,20h,53h,69h,67h,73h
RET
output4: db 1ah,50h,72h,65h,73h,73h,20h,31h,20h,46h,6fh,72h,20h,46h
db 69h,6ch,74h,65h,72h,65h,64h,0ah,0dh,50h,6fh,73h,20h
db 6fh,72h,20h,32h,20h,4fh,74h,68h,65h,72h,20h,53h,69h,67h,73h
RET
output5: db 1ah,50h,72h,65h,73h,73h,20h,31h,20h,46h,6fh,72h,20h,43h
db 6fh,6dh,6dh,61h,6eh,64h,0ah,0dh,6fh,72h,20h,32h,20h,46h
db 6fh,72h,20h,4fh,74h,68h,65h,72h,20h,53h,69h,67h,73h
RET
$include(lcddrv3.a51) ; LCD subrountines
escflag equ psw.5 ;LCD equate
END