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):
In this first section: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
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.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
These aliases would have been earlier equated as follows:
Also if your counter is going backwards from the desired direction, all you have to do is swap the previous assignments:Code:ENCA VAR PORTC.4 ; any port, any bit ENCB VAR PORTC.5 ; any port, any bit
And here is the code that determines if the encoder has moved or not:Code:ENCB VAR PORTC.4 ; any port, any bit ENCA VAR PORTC.5 ; any port, any bit
Here is where we determine the encoder's direction of travel: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.
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:;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.
Lastly, be sure to include this as part of your ISR "restore" code: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
In order to determine if an encoder change has occured within your PBP program just check and then clear the ENCDRnew bit.Code:restore movf _newenc,W ; update encoder OLD to equal NEW movwf _oldenc
And here are the equates for some of the variables I am using:
I hope this helps and doesn't just confuse the situation,Code:newenc var byte oldenc var byte tmpenc var byte direnc var bit ENCDRnew var bit




Bookmarks