Interrupts interfering with PRINT
Hello,
I have a 16f876a running at 20MHz. It's connected to 2 H-bridges (of Bob Blick's design as can be seen at http://www.bobblick.com/techref/proj...e/hbridge.html) which I'm using to control two motors via PWM. Initially I was doing the pwm in software manually on each cycle round my program by varying the on/off time ratio at the end of each loop round the program. This worked, but because I was doing quite a few other things each loop I was getting a very low frequency of pwm - around 10-20hz I believe. (I don't have an oscillioscope so can't be sure of the exact frequency, but that's my best guestimate).
The logical solution I figured was to do the pwm using an interrupt routine driven by timer0. This works - I'm getting an (audibly and visibly) much smoother control of the motor speed. Trouble is the LCD display to which I was outputting program data each loop is now showing partially or completely scrambled data. I assume that the PRINT commands I'm using are being rudely interrupted by my timer interrupt and that this is screwing up the timing of the data transmission to the LCD display.
How can I avoid this? I've tried reducing the frequency of the pwm (by adjusting the values placed in PS2:PS0) but this doesn't solve the problem, not to mention that it defeats the point of the whole exercise. My ISR is fairly short (assembly code below), so I presume I'm not taking too long.
Incidentally - if you're wondering why I don't just use hardware pwm, the problem is that each h-bridge requires an input for each direction of motor operation - that's 4 outputs from the PIC in total. As I recall (can't find the specs now), an 876a only has 2 or 3 hardware pwm channels.
If it's the case that serivicing interrupts messes up the timing for picbasic commands doesn't that rather limit their utility? Or am I just doing something really wrong.
Any help/ideas/pointers is really appreciated because I don't think I can progress any further without some assistance.
Thanks,
Luke
Here's the asm code for the ISR. I am doing a RESUME at the end. pwmm1spd is a byte variable with the desired motor speed in it. intCount is a byte variable that just increments each time round the ISR. each time it hits zero is one cycle of pwm, so my pwm has a 'resolution' of 256 degress of on/offness. Hope that makes sense:
movfw pwmm1spd
subwf intCount, w
btfsc STATUS, C
goto PWMOFF
PWMON:
movlw 1
subwf direction, w
btfsc STATUS, Z
goto FORWARD
bcf M1B
bsf M1F
bcf M2F
bsf M2B
goto DONEPWM
FORWARD:
bcf M2B
bsf M2F
bcf M1F
bsf M1B
goto DONEPWM
PWMOFF:
; Turn everything off
bcf M1F ; Since this is the down part of the cycle
bcf M1B ; Easier to turn everything off than test
bcf M2F ; which motors to turn off...
bcf M2B
DONEPWM:
decfsz intCount, 1 ; Decrement intCount
goto intDoneStuff ; if NOT ZERO, then jump to intDoneStuff
movlw 255 ; otherwise (if 0)... 255 into w
movwf intCount ; reset counter
intDoneStuff:
bcf T0IF ; Clear the TMR0 overflow flag