Darryl & Joe

Thanks for your comment - yes I do have code that sets RCON,7 (IPEN)
to enable priority levels on interrupts.

I've made an XY plotter/scanner using stepper motors and cheap Chinese linear bearings (about $10 each!). Only got the 'movement/plot bit' done so far and will add the scan later (Paralax Line Scan module).

I went to assembler so that I could drive X and Y motors at the same time to get diagonal moves. This bit of the code works like:

1. In PBP set the X_steps (Nx) and Y_steps (Ny)
2. In PBP work out the periods of the pulses (Px znd Py) so that the time to make the X/Y moves are the same T(move) = Nx.Px = Ny.Py
3. Send the variables to the ASM code
4. Use Timer0 to interrupt (high priority) for Px
5. Use Timer1 to interrupt for Py
6. Decrament Nx whenever an X pulse is sent and halt at zero
7. Stop and return to PBP

It's the 'stopping' that took me two days to sort out and the guilty party was the IPEN bit - and an inexperienced asm programmer!

Happy to post the code - sorry - I've used TABS and it looks terrible at the moment:

Code:
;******************************************************************************
;                                                                             *
;	Filename: WL_Scanner_01                                                *
;	Date:	February 2010                                                   *
;                                                                             * 
;******************************************************************************

;******************************************************************************
;                                                                             *
;	Function: Drive two stepper motors with timers/interrupts	        *
;	Files Required: P18F8722.INC                                           *
;                                                                             *
;******************************************************************************

	LIST P=18F8722		; Directive to define processor
	#include <P18F8722.INC>	; Drocessor specific variable definitions
	
;******************************************************************************
;	Configuration bits
	CONFIG	OSC = HSPLL	; Run at 4X speed
	CONFIG	CP0=OFF	; Disable code protect				
	CONFIG	PWRT = OFF	; Power up timer off so DEBUG works            
	CONFIG	WDT=OFF	; WDT off
	CONFIG	LVP = OFF	; LVP off
	CONFIG	WAIT = OFF	; External bus data wait disabled
;******************************************************************************
;	Variable definitions in data memory
WREG_TEMP	equ	0x010		; Variable used for context saving 
STATUS_TEMP	equ	0x011		; Variable used for context saving
BSR_TEMP	equ	0x012		; Variable used for context saving
Count_pulse	equ	0x013		; Loop delay in 5 uS pulse to motor driver
X_delay_lb	equ	0x014		; Inter-pulse delay for X axis, high byte
X_delay_hb	equ	0x015		; Inter-pulse delay for X axis, low byte
Y_delay_lb	equ	0x016		; Inter-pulse delay for Y axis, high byte
Y_delay_hb	equ	0x017		; Inter-pulse delay for Y axis, low byte
X_steps_lb	equ	0x018		; Number of steps to do on X axis
X_steps_hb	equ	0x019		; Y steps not needed as Tx.Dx=Ty.Dy

;******************************************************************************
;	Reset vector in program memory
	ORG	0x0000
	goto	Main_ASM		; Go to start of main code
;******************************************************************************
;	High priority interrupt vector in program memory
	ORG	0x0008
	goto	High_int		; Go to high priority interrupt routine
;******************************************************************************
;	Low priority interrupt vector and routine in program memory, when Timer1
;	overflows send out stepper drive pulse for Y axis on PORTD.3
	ORG	0x0018
	movff	STATUS,STATUS_TEMP	; save STATUS register
	movff	WREG,WREG_TEMP	; save working register
	movff	BSR,BSR_TEMP		; save BSR register

	bcf	INTCON,7		; Disable all interrupts
	bsf	PORTD,3		; High PORTD.3
	call	Pulse_out		; Delay for 10 microseconds
	bcf	PORTD,3		; High PORTD.3
	bcf	PIR1,0			; Clear Timer1 interrupt flag
	movff	Y_delay_hb,TMR1H	; Load Timer1 with Y_delay
	movff	Y_delay_lb,TMR1L	; Load timer1 with Y_delay
	
	movff	BSR_TEMP,BSR		; restore BSR register
	movff	WREG_TEMP,WREG	; restore working register
	movff	STATUS_TEMP,STATUS	; restore STATUS register
	
	bsf	INTCON,7		; Enable interrupts	
	retfie
	
;******************************************************************************
;	High priority interrupt routine, when Timer0 overflows, send out stepper
;	drive pulse for X axis on PORTD.0
High_int:
	bcf	INTCON,7		; Disable interrupte
	bsf	PORTD,0		; High PORTD.0
	call	Pulse_out		; Send 5uS pulse on PORTB.0
	bcf	PORTD,0		; Low PORTD.0
	bcf	INTCON,2		; Clear Timer0 interrupt flag
	movff	X_delay_hb,TMR0H	; Load timer0 with X_delay
	movff	X_delay_lb,TMR0L	; Load timer0 with X_delay
		
	decf	X_steps_lb		; Decrement X_steps				
	bsf	INTCON,7		; Enable interrupts						
	retfie	1
	
;******************************************************************************
;                                                                             *
;                               SUBROUTINES                                   *
;                                                                             * 
;******************************************************************************
	
Pulse_out:			; Delay = 3.n + 7 [0.1 microseconds]
	movlw	0xff		; Load w with n
	movwf	Count_pulse	; Load Count with n
Pulse_loop:
	decfsz	Count_pulse	; Decrament the file Count
	goto	Pulse_loop	; Loop if not zero
	return
	
;******************************************************************************
;                                                                             *
;                                  MAIN ASM                                   *
;                                                                             * 
;******************************************************************************
	
Main_ASM:	
	clrf	TRISA			; PORTA is output
	clrf	TRISB     		; PORTB is output
	clrf	TRISC			; PORTC is output
	clrf	TRISD     		; PORTD is output
	clrf	TRISE			; PORTE is output
	clrf	TRISF			; PORTF is output
	clrf	TRISG			; PORTG is output
	clrf	TRISH			; PORTH is output
	clrf	TRISJ			; PORTJ is output
	
	clrf	PORTA			; Clear PORTA
	clrf	PORTB			; Clear PORTB
	clrf	PORTC			; Clear PORTC
	clrf	PORTD			; Clear PORTD
	clrf	PORTE			; Clear PORTE
	clrf	PORTF			; Clear PORTF
	clrf	PORTG			; Clear PORTG
	clrf	PORTH			; Clear PORTH
	clrf	PORTJ			; Clear PORTJ
	
	movlw	0x0f
	movwf	ADCON1			; PORTA is digital I/O
	movlw	0x07
	movwf	CMCON			; Comparator off
	
; Set up interrupt conditions for Timer0 and Timer1	
	bsf	RCON,7			; Enable priority levels on interrupts,IPEN=1
	bsf	INTCON,7		; Enable all high priority interrupts
	bsf	INTCON,6		; Enable all low priority interrupts
	bcf	INTCON,3		; Disable PORTB interrupts
	bsf	INTCON2,2		; Make Timer0 overflow high priority
	bcf	IPR1,0			; Make Timer1 overflow low priority
	bsf	INTCON,5		; Enable Timer0 overflow flag
	bsf	PIE1,0			; Enable Timer1 overflow flag		
	
; Set up Timer0 conditions				
	bcf	T0CON,6		; Timer0 uses 16 bits
	bcf	T0CON,5		; Timer0 uses internal osc
	bcf	T0CON,4		; Timer0 count on rising edge og osc
	bsf	T0CON,3		; Timer0 pre-scaler not assigned
	clrf	TMR0L			; Zero the clock
	clrf	TMR0H			; Zero the clock				
	bsf	T0CON,7		; Timer0 on
		
; Set up Timer1 conditions
	bsf	T1CON,7		; Timer1 uses 16 bits
	bcf	T1CON,1		; Timer1 uses internal osc
	clrf	TMR1L			; Zero the clock
	clrf	TMR1H			; Zero the clock
	bsf	T1CON,0		; Timer1 on	
	
;	Temp code to simmulate PBP input for the delays
	movlw	0x00
	movwf	X_delay_lb
	movlw	0x00
	movwf	X_delay_hb
	movlw	0x00
	movwf	Y_delay_lb
	movlw	0x00
	movwf	Y_delay_hb
	movlw	0xff
	movwf	X_steps_lb
	movlw	0xff
	movwf	X_steps_hb					
;	End of Temp code	

; Check if X_steps_lb=0 (decremented in high priority interrupt)
; If so, check X_steps_hb and if zero, end
; If not, decrement X_steps_hb, set X_steps_lb and go again	
Main_loop:
	movff	X_steps_hb,PORTC
	;comf	PORTC,1	; LEDS active low so invert
	movff	X_steps_lb,PORTD
	;comf	PORTD,1				
	tstfsz	X_steps_lb	; Test, skip next if zero
	goto	Main_loop	; More steps to do, so loop
	tstfsz	X_steps_hb	; Test, skip next if zero
	goto	Re_load_lb
	goto	All_done
	
Re_load_lb:
	decf	X_steps_hb,1	; Decrement hb and then carry to lb
	setf	X_steps_lb	; Decremented hb, so load ff to lb
	goto	Main_loop
	
All_done:	
	bcf	RCON,7		; Clear IPEN=0, disable priority interrupts
	end			; IPEN must be cleared or asm keeps running
Regards Bill Legge