I don't know if this will help or not, but I made some changes to some earlier code I posted which was aimed at the 18F series. Besides there being a few flaws with the syntax of the rotate function in the original code, I just didn't like some aspects of it.
So here is an example of what I am now using to check an encoder's direction and movement (within Interrupt Service Routine):
Code:
chk_encoder
;Read latest input from ENCODER & put the value in NEW.
clrf _newenc ; clear "new" encoder bit pair storage,
btfsc _ENCA ; and transfer state of encoder bits.
bsf _newenc,0
btfsc _ENCB
bsf _newenc,1
;Compare previous encoder inputs (OLD) with latest ones (NEW).
movf _newenc,W ;Move the contents of NEW to TEMP and OLD to W
movwf _tmpenc ;in order to compare them with XOR.
movf _oldenc,W
xorwf _tmpenc,F ;XOR previous inputs (in W) with latest inputs
;(in TEMP) to see if they are equal.
btfsc STATUS,Z ;Test result and skip next line if zero flag clear.
goto restore ;Result = zero. Previous inputs equal latest
;inputs. Rotary encoder did not move. Return
;from interrupt.
;Result is a non-zero value. Rotary encoder moved. Determine direction.
bsf _ENCDRnew ; flag that encoder value has changed
bcf STATUS,C ;Clear the carry bit in the status register and
rlcf _oldenc,F ;left shift it into OLD to align bit 1 of OLD
;with bit 0 of NEW.
movf _newenc,W ;Move the contents of NEW to W in order to XOR.
xorwf _oldenc,F ;XOR previous inputs (in OLD) with latest
;inputs (in W) to determine CW or CCW.
btfsc _oldenc,1 ;Test bit 1 of result (in OLD). Skip next line
;if it is 0 (direction is CCW).
goto encoder_up ;Bit is 1 (direction is CW). Go around Down
;and increment counter.
encoder_down
bcf _direnc ; clear direction bit = CCW (count down)
goto countdown
encoder_up
bsf _direnc ; set direction bit = CW (count up)
;drops into countup part of routine
In this first section:
Code:
;Read latest input from ENCODER & put the value in NEW.
clrf _newenc ; clear "new" encoder bit pair storage,
btfsc _ENCA ; and transfer state of encoder bits.
bsf _newenc,0
btfsc _ENCB
bsf _newenc,1
We are using aliases for the actual encoder "A" and "B" inputs. By doing this , it makes your code more transportable to different devices and/or board configurations.
These aliases would have been earlier equated as follows:
Code:
ENCA VAR PORTC.4 ; any port, any bit
ENCB VAR PORTC.5 ; any port, any bit
Also if your counter is going backwards from the desired direction, all you have to do is swap the previous assignments:
Code:
ENCB VAR PORTC.4 ; any port, any bit
ENCA VAR PORTC.5 ; any port, any bit
And here is the code that determines if the encoder has moved or not:
Code:
;Compare previous encoder inputs (OLD) with latest ones (NEW).
movf _newenc,W ;Move the contents of NEW to TEMP and OLD to W
movwf _tmpenc ;in order to compare them with XOR.
movf _oldenc,W
xorwf _tmpenc,F ;XOR previous inputs (in W) with latest inputs
;(in TEMP) to see if they are equal.
btfsc STATUS,Z ;Test result and skip next line if zero flag clear.
goto restore ;Result = zero. Previous inputs equal latest
;inputs. Rotary encoder did not move. Return
;from interrupt.
Here is where we determine the encoder's direction of travel:
Code:
;Result is a non-zero value. Rotary encoder moved. Determine direction.
bsf _ENCDRnew ; flag that encoder value has changed
bcf STATUS,C ;Clear the carry bit in the status register and
rlcf _oldenc,F ;left shift it into OLD to align bit 1 of OLD
;with bit 0 of NEW.
movf _newenc,W ;Move the contents of NEW to W in order to XOR.
xorwf _oldenc,F ;XOR previous inputs (in OLD) with latest
;inputs (in W) to determine CW or CCW.
btfsc _oldenc,1 ;Test bit 1 of result (in OLD). Skip next line
;if it is 0 (direction is CCW).
goto encoder_up ;Bit is 1 (direction is CW). Go around Down
;and increment counter.
Besides determining which counter routine to execute (countup or countdown), a direction bit (direnc) is also assigned that can be accessed by the main PBP program and used to determine, or display the last known direction of the encoder.
Code:
encoder_down
bcf _direnc ; clear direction bit = CCW (count down)
goto countdown
encoder_up
bsf _direnc ; set direction bit = CW (count up)
;drops into countup part of routine
Lastly, be sure to include this as part of your ISR "restore" code:
Code:
restore
movf _newenc,W ; update encoder OLD to equal NEW
movwf _oldenc
In order to determine if an encoder change has occured within your PBP program just check and then clear the ENCDRnew bit.
And here are the equates for some of the variables I am using:
Code:
newenc var byte
oldenc var byte
tmpenc var byte
direnc var bit
ENCDRnew var bit
I hope this helps and doesn't just confuse the situation,
Bookmarks