View Single Post
Old 02-02-2005, 10:32 AM   #2 (permalink)
toblerone
Registered User
 
toblerone's Avatar
 
Join Date: Jul 2004
Posts: 11
toblerone is on a distinguished road
The solution

I worked a final solution, which involved rethinking the code entirely, here it is for anyone interested

Code:
$NOMOD51
$INCLUDE (REG552.H)

ORG 0 		/*PROGRAM START VECTOR*/
JMP main
ORG 0003H	/*EXTERNAL INT0 START VECTOR*/
JMP runKeyISR
/************************************************
*location for KeyID = A				*
*						*
*Main program sets interrupt INT0, this then 	*
*calls the scanKeypad, clearPad then runs Mx and* 
* jumps back to refreshing the motors, waiting 	*
*for INT0					*
* Ready for emulation 17/2/05. c Toby Mole 2005	*
************************************************/

ORG 0030H	/*MAIN START VECTOR*/

main:
	MOV TMOD, #11H /*SET T0 & T1 AS 16 BIT TIMERS*/
	SETB IT0 	/*SET EX0 AS LEVEL ACTIVATED*/
	SETB EX0 	/*SET EXTERNAL KEY PRESS INT*/
	MOV PWMP, #0EAH	/*Fpwm = 12Mhz / (2x (1+EAH) x255) = 100Hz*/
	CLR P1.0 	/*SET ROWS AS OUTPUTS FOR SCAN*/
	CLR P1.1
	CLR P1.2
	CLR P1.3
	CLR P1.4
	SETB P1.6 	/*SET COLUMNS AS INPUTS FOR SCAN*/
	SETB P1.7
	CALL motorCenter	/*CENTRE ALL MOTORS AND INITIALISE R1-R5*/
	SETB EA 	/*ENABLE INTS*/
loop:	CALL refresh
	JMP loop	/*WAIT FOR KEY DOWN INT IF NO KEY FOUND YET*/		

runKeyISR:
	CLR EX0 	/*DISABLE INT0 INT*/
	CALL debounce	/*RUN DELAY TO CANCEL OUT DEBOUNCE*/
	CALL scanPad	/*GET KEY DOWN NUMBER*/
	CALL clearPad 	/*IN PLACE OF waitForKeyRelease*/
	CALL disablePins/*MAKE SURE ALL PINS ARE DISABLED FROM REFRESH ROUTINE*/
	CALL loadValue	/*SELECT Rx AND MOVE CURRENT mX VALUE TO PWM0*/
	CALL enablePin	/*ENABLE Mx PIN*/
	CALL run	/*INC PWM & RUN DELAY*/
	CALL disablePins/*DISABLE*/
	CALL copyNewValue	/*COPY NEW CURRENT VALUE BACK TO Rx*/
	CLR IE0 	/*CLR INT0 FLAG*/
	SETB EX0 	/*ENABLE INT0 INT*/
	RETI

motorCenter:
/********************************************************
*This function loads the centering value to the PWM,	*
*enables all motors and runs them, copies the 	 	*
*centering (current), value to the corresponding 	*
*registers. Then returns 				*
********************************************************/
			/*LOAD UP PWM0 FOR CENTERING*/
	MOV PWM0, #0EFH	/*DC = PWM0 / (255-PWM0) I.E. 239=14.93%=EF*/
	MOV P2, #00H	/*ENABLE (CLEAR) ALL O/P PIN BUFFERS*/
	CALL delay	/*DELAY FOR MOTOR MOVE TIME*/
	MOV P2, #1FH	/*DISABLE (SET) ALL O/P PIN BUFFERS*/
	MOV R1, PWM0	/*COPY PWM0 CENTERED VALUE TO Rx*/
	MOV R2, PWM0
	MOV R3, PWM0
	MOV R4, PWM0
	MOV R5, PWM0
	RET

refresh:
/********************************************************
*This function refreshes all motors with their current	*
*values, and then returns.				*
********************************************************/

	MOV A, #01H	/*LOAD FOR M1*/
	CALL loadValue	/*SELECT REGISTER AND COPY INTO PWM0*/
	CALL enablePin	/*ENABLE PIN1*/
	CALL delay	/*RUN M1*/
	CALL disablePins/*DISABLE PIN*/
	MOV A, #02H	/*LOAD FOR M2*/
	CALL loadValue	/*SELECT REGISTER AND COPY INTO PWM0*/
	CALL enablePin	/*ENABLE PIN2*/
	CALL delay	/*RUN M2*/
	CALL disablePins/*DISABLE PIN*/
	MOV A, #03H	/*LOAD FOR M3*/
	CALL loadValue	/*SELECT REGISTER AND COPY INTO PWM0*/
	CALL enablePin	/*ENABLE PIN3*/
	CALL delay	/*RUN M3*/
	CALL disablePins/*DISABLE PIN*/
	MOV A, #04H	/*LOAD FOR M4*/
	CALL loadValue	/*SELECT REGISTER AND COPY INTO PWM0*/
	CALL enablePin	/*ENABLE PIN4*/
	CALL delay	/*RUN M4*/
	CALL disablePins/*DISABLE PIN*/
	MOV A, #05H	/*LOAD FOR M5*/
	CALL loadValue	/*SELECT REGISTER AND COPY INTO PWM0*/
	CALL enablePin	/*ENABLE PIN5*/
	CALL delay	/*RUN M5*/
	CALL disablePins/*DISABLE PIN*/
	RET

debounce:
/********************************************************
*This function is a delay loop to prevent wrong readings*
*from the keypad after INT0 due to contact bounce	*
********************************************************/

	CLR TR0		/*STOP TIMER0 IN CASE ITS LEFT RUNNING*/
	MOV TH0, #8AH	/*SET TIMER0 FOR 35,536 (8AD0H)*/
	MOV TL0, #0D0H 	
	SETB TR0 	/*START TIMER0*/
	JNB TF0, $ 	/*WAIT FOR OVERFLOW*/
	CLR TF0 	/*CLEAR OVERFLOW*/
	CLR TR0 	/*STOP TIMER0*/
	RET

scanPad:
/********************************************************
*This function selects a row for the colscan function	*
*Then returns.						*
********************************************************/
	MOV A,0H	/*CLEAR A READY FOR NEW KEY DOWN NUMBER*/
	CLR P1.0	/*CLEAR 1ST ROW*/
	SETB P1.1	/*SET ALL OTHER ROWS*/
	SETB P1.2
	SETB P1.3
	SETB P1.4
	CALL colScan	/*SCAN THE COLUMNS*/
	JB 40H, return	/*TEST FOR KEY*/
	SETB P1.0
	CLR P1.1	/*CLEAR 2ND ROW*/
	SETB P1.2	/*SET ALL OTHER ROWS*/
	SETB P1.3
	SETB P1.4
	CALL colScan 	/*SCAN THE COLUMNS*/
	JB 40H, return	/*TEST FOR KEY*/
	SETB P1.0
	SETB P1.1
	CLR P1.2	/*CLEAR 3RD ROW*/
	SETB P1.3	/*SET ALL OTHER ROWS*/
	SETB P1.4
	CALL colScan 	/*SCAN COLUMNS*/
	JB 40H, return	/*TEST FOR KEY*/
	SETB P1.0	/*SET ALL OTHER ROWS*/
	SETB P1.1
	SETB P1.2
	CLR P1.3	/*CLEAR 4TH ROW*/
	SETB P1.4	
	CALL colScan 	/*SCAN COLUMNS*/
	JB 40H, return	/*TEST FOR KEY*/
	SETB P1.0	/*SET ALL OTHER ROWS*/
	SETB P1.1
	SETB P1.2
	SETB P1.3
	CLR P1.4	/*CLEAR 5TH ROW*/	
	CALL colScan 	/*SCAN COLUMNS*/
return:	ADD A, #01H	/*BIAS KEYID (INC A?)*/
	RET

colScan:
/********************************************************
*This function checks each column in a row and 		*
*increments a counter, keyID, if keydown not found.	*
********************************************************/

	JNB P1.6, skip	/*SCAN FIRST COLUNM*/
	INC A		/*INC A FOR KEY ID*/
	JNB P1.7, skip	/*SCAN SECOND COLUMN*/
	INC A		/*INC A FOR KEY ID*/
	RET		/*RETURN IF NO KEY FOUND ON THAT COLUMN*/
skip:	SETB 40H 	/*KEY FOUND SO SET TO JUMP OUT OF JNB WAIT LOOP*/
	RET

clearPad:
/********************************************************
*This function clears the rows ready for a new reading.	*
* Then returns						*
********************************************************/

	CLR P1.0	/*CLEAR THE KEYPAD ROWS READY FOR NEXT SCAN*/
	CLR P1.1
	CLR P1.2
	CLR P1.3
	RET

loadValue:
/********************************************************
*	This function uses the keyID in the ACC, to	*
*select the correct register from which it obtains the 	*
*corresponding current motor's PWM value and loads it to*
*the PWM0. Then returns					*
********************************************************/
	
	CJNE A, #01H, mov1skip	/*IF 1 COPY FROM R1*/
	MOV PWM0, R1		/*MOV CURRENT M1 VALUE TO PWM0*/
	JMP endSkip		/*JUMP TO END OF FUNCTION*/
mov1skip:
	CJNE A, #02H, mov2skip	/*IF 2 COPY FROM R2*/
	MOV PWM0, R2		/*MOV CURRENT M2 VALUE TO PWM0*/
	JMP endSkip		/*JUMP TO END OF FUNCTION*/
mov2skip:
	CJNE A, #03H, mov3skip	/*IF 3 COPY FROM R3*/
	MOV PWM0, R3		/*MOV CURRENT M3 VALUE TO PWM0*/
	JMP endSkip		/*JUMP TO END OF FUNCTION*/
mov3skip:
	CJNE A, #04H, mov4skip	/*IF 4 COPY FROM R4*/
	MOV PWM0, R4		/*MOV CURRENT M4 VALUE TO PWM0*/
	JMP endSkip		/*JUMP TO END OF FUNCTION*/
mov4skip:
	CJNE A, #05H, mov5skip	/*IF 5 COPY FROM R5*/
	MOV PWM0, R5		/*MOV CURRENT M5 VALUE TO PWM0*/
	JMP endSkip
mov5skip:
	CJNE A, #06H, mov6skip	/*IF 6 COPY FROM R1*/
	MOV PWM0, R1		/*MOV CURRENT M1 VALUE TO PWM0*/
	JMP endSkip		/*JUMP TO END OF FUNCTION*/
mov6skip:
	CJNE A, #07H, mov7skip	/*IF 7 COPY FROM R2*/
	MOV PWM0, R2		/*MOV CURRENT 2 VALUE TO PWM0*/
	JMP endSkip		/*JUMP TO END OF FUNCTION*/
mov7skip:
	CJNE A, #08H, mov8skip	/*IF 8 COPY FROM R3*/
	MOV PWM0, R3		/*MOV CURRENT M3 VALUE TO PWM0*/
	JMP endSkip		/*JUMP TO END OF FUNCTION*/
mov8skip:	
	CJNE A, #09H, mov9skip	/*IF 9 COPY FROM R4*/
	MOV PWM0, R4		/*MOV CURRENT M4 VALUE TO PWM0*/
	JMP endSkip		/*JUMP TO END OF FUNCTION*/
mov9skip:
	CJNE A, #10H, endSkip	/*IF 10 COPY FROM R5*/
	MOV PWM0, R5		/*MOV CURRENT M5 VALUE TO PWM0*/
	JMP endSkip		/*JUMP TO END OF FUNCTION*/
endSkip:RET			/*RETURN TO MAIN*/
	
enablePin:
/********************************************************
*This function uses the keypadid in ACC to enable the	*
*correct Mx pin. Then returns				*
********************************************************/

	CJNE A, #01H, en1skip	/*IF NOT 1 TRY NEXT*/
	CLR P2.0		/*IF 1 ENABLE (CLEAR) PIN*/
	JMP en10skip		/*JUMP TO END*/
en1skip:CJNE A, #02H, en2skip	/*IF NOT 2 TRY NEXT*/
	CLR P2.1
	JMP en10skip
en2skip:CJNE A, #03H, en3skip	/*IF NOT 3 TRY NEXT*/
	CLR P2.2
	JMP en10skip
en3skip:CJNE A, #04H, en4skip	/*IF NOT 4 TRY NEXT*/
	CLR P2.3
	JMP en10skip
en4skip:CJNE A, #05H, en5skip	/*IF NOT 5 TRY NEXT*/
	CLR P2.4
	JMP en10skip
en5skip:CJNE A, #06H, en6skip	/*IF NOT 6 TRY NEXT*/
	CLR P2.0
	JMP en10skip
en6skip:CJNE A, #07H, en7skip	/*IF NOT 7 TRY NEXT*/
	CLR P2.1
	JMP en10skip
en7skip:CJNE A, #08H, en8skip	/*IF NOT 8 TRY NEXT*/
	CLR P2.2
	JMP en10skip
en8skip:CJNE A, #09H, en9skip	/*IF NOT 9 TRY NEXT*/
	CLR P2.3
	JMP en10skip
en9skip:CJNE A, #10H, en10skip	/*IF NOT 10 TRY NEXT*/
	CLR P2.4
	JMP en10skip
en10skip:
	RET

run:
/********************************************************
*This function checks that the value is within the Mx 	*
*boundries, if it is, it changes the pulse width for the*
*Mx by xxus then runs a delay for 5ms, and returns.	*
*If not, it returns doing nothing.			*
********************************************************/
	
	MOV R0, PWM0	/*MOV PWM0 TO R0 FOR COMPARE PAIR*/
	CJNE R0, #0F1H, skip1	/*UPPER LIMIT (241) AT 17% D.C.*/
	RET		/*IF NOT WITHIN LIMIT DO NOTHING AND RETURN*/
skip1:	CJNE R0, #0EDH, skip1a	/*LOWER LIMIT (237) AT 13% D.C.*/
	RET		/*IF NOT WITHIN LIMIT DO NOTHING AND RETURN*/
skip1a:	CJNE A, #01H, run2	/*IF 1 RUN 1 UP*/
	JMP skip2
run2:	CJNE A, #02H, run3	/*IF 2 RUN 2 UP*/
	JMP skip2
run3:	CJNE A, #03H, run4	/*IF 3 RUN 3 UP*/
	JMP skip2
run4:	CJNE A, #04H, run5	/*IF 4 RUN 4 UP*/
	JMP skip2
run5:	CJNE A, #05H, run6	/*IF 5 RUN 5 UP*/
	JMP skip2
run6:	CJNE A, #06H, run7	/*IF 6 RUN 1 DOWN*/
	JMP skip3
run7:	CJNE A, #07H, run8	/*IF 7 RUN 2 DOWN*/
	JMP skip3
run8:	CJNE A, #08H, run9	/*IF 8 RUN 3 DOWN*/
	JMP skip3
run9:	CJNE A, #09H, run10	/*IF 9 RUN 4 DOWN*/
	JMP skip3
run10:	CJNE A, #10H, endSkip1	/*IF 10 RUN 5 DOWN*/
	JMP skip3
	RET			/*IN CASE NO ID FOUND, RETURN*/
skip2:	MOV R0, A	/*TEMPORARILY SAVE ACC TO R0*/
	MOV A, PWM0	/*COPY CURRENT Mx VALUE FROM PWM0 TO A*/
	INC A		/*STEP PWM0 UP BY 1%*/
	MOV PWM0, A	/*MOV NEW RESULTANT VALUE INTO PWM0*/
	CALL delay	/*RUN DELAY WHILE Mx MOVES*/
	MOV A, R0	/*MOVE ACC BACK FROM R0*/
	RET
skip3:	MOV R0, A	/*TEMPORARILY SAVE ACC TO R0*/
	MOV A, PWM0	/*COPY CURRENT Mx VALUE FROM PWM0 TO A*/
	DEC A		/*STEP PWM0 DOWN BY 1%*/
	MOV PWM0, A	/*MOV NEW RESULTANT VALUE INTO PWM0*/
	CALL delay	/*RUN DELAY WHILE Mx MOVES*/
	MOV A, R0	/*MOVE ACC BACK FROM R0*/
endSkip1:
	RET

disablePins:
/********************************************************
*This function disables all pins including any enabled	*
*so as to stop any PWM output, and to make pins ready 	*
*for re-entry to the refresh loop. Then returns		*
********************************************************/

	MOV P2, #1FH	/*DISABLE (SET) ALL O/P PIN BUFFERS*/
	RET		

copyNewValue:
/********************************************************
*This function uses the keyID in the ACC, to select the	*
*correct register to which it copies the corresponding	*
*current motor's new PWM value. Then returns		*
********************************************************/
	
	CJNE A, #01H, testv2	/*IF 1 copy MOTOR 1*/
	MOV R1, PWM0		/*MOV NEW M1 VALUE TO R1*/
	JMP endSkip2		/*JUMP TO END OF FUNCTION*/
testv2:	CJNE A, #02H, testv3	/*IF 2 copy MOTOR 2*/
	MOV R2, PWM0		/*MOV NEW M2 VALUE TO R2*/
	JMP endSkip2		/*JUMP TO END OF FUNCTION*/
testv3:	CJNE A, #03H, testv4	/*IF 3 copy MOTOR 3*/
	MOV R3, PWM0		/*MOV NEW M3 VALUE TO R3*/
	JMP endSkip2		/*JUMP TO END OF FUNCTION*/
testv4:	CJNE A, #04H, testv5	/*IF 4 copy MOTOR 4*/
	MOV R4, PWM0		/*MOV NEW M4 VALUE TO R4*/
	JMP endSkip2		/*JUMP TO END OF FUNCTION*/
testv5:	CJNE A, #05H, testv6	/*IF 5 copy MOTOR 5*/
	MOV R5, PWM0		/*MOV NEW M5 VALUE TO R5*/
	JMP endSkip2		/*JUMP TO END OF FUNCTION*/
testv6:	CJNE A, #06H, testv7	/*IF 6 copy MOTOR 1*/
	MOV R1, PWM0		/*MOV NEW M1 VALUE TO R1*/
	JMP endSkip2		/*JUMP TO END OF FUNCTION*/
testv7:	CJNE A, #07H, testv8	/*IF 7 copy MOTOR 2*/
	MOV R2, PWM0		/*MOV NEW M2 VALUE TO R2*/
	JMP endSkip2		/*JUMP TO END OF FUNCTION*/
testv8:	CJNE A, #08H, testv9	/*IF 8 copy MOTOR 3*/
	MOV R3, PWM0		/*MOV NEW M3 VALUE TO R3*/
	JMP endSkip2		/*JUMP TO END OF FUNCTION*/
testv9:	CJNE A, #09H, testv10	/*IF 9 copy MOTOR 4*/
	MOV R4, PWM0		/*MOV NEW M4 VALUE TO R4*/
	JMP endSkip2		/*JUMP TO END OF FUNCTION*/
testv10:CJNE A, #10H, endSkip2	/*IF 10 copy MOTOR 5*/
	MOV R5, PWM0		/*MOV NEW M5 VALUE TO R5*/
endSkip2:
	RET			/*RETURN TO MAIN*/

delay:
/********************************************************
*This function is a basic delay for 5ms	while PWM is	*
*output.						*
********************************************************/

	CLR TR1		/*STOP TIMER1 IN CASE ITS LEFT RUNNING*/
	MOV TH1, #0ECH	/*SET TIMER1 FOR 60,536 (EC78H)*/
	MOV TL1, #78H 	
	SETB TR1 	/*START TIMER1*/
	JNB TF1, $ 	/*WAIT FOR OVERFLOW*/
	CLR TF1 	/*CLEAR OVERFLOW*/
	CLR TR1 	/*STOP TIMER1*/
	RET

END
Note the first 2 lines; The first suppresses reg51 code so the second can safely include reg552 (Im using a 87C552)

Last edited by toblerone; 02-17-2005 at 12:09 PM.
toblerone is offline   Reply With Quote