Hi, Guys. I know you've discussed rotary encoders in the past, and I'd like to share my solution, just for fun.
Below is the interrupt routine for a quadrature rotary encoder. It was written for a PIC16CE625 back in 2000, and should run on any PIC16. It uses the port b change interrupt, with the 'A' signal tied to RB7 and the 'B' signal tied to RB6.
The nice thing about it is that it requires no signal conditioning. It's very fast, so high resolution/high speed encoders are no problem. It can accumulate up to +127/-128 counts before requiring being 'read out'.
Typically, the main program waits till the 'rawrdy' flag is set. At that point, it adds the 8 bit '_encinc' value to an accumulator (of arbitrary size), zeros '_encinc', and clears the flag. Remember to disable ints during this process, or corrupted counts will occur.
Happy to answer questions about it. Enjoy!
Below is the interrupt routine for a quadrature rotary encoder. It was written for a PIC16CE625 back in 2000, and should run on any PIC16. It uses the port b change interrupt, with the 'A' signal tied to RB7 and the 'B' signal tied to RB6.
The nice thing about it is that it requires no signal conditioning. It's very fast, so high resolution/high speed encoders are no problem. It can accumulate up to +127/-128 counts before requiring being 'read out'.
Typically, the main program waits till the 'rawrdy' flag is set. At that point, it adds the 8 bit '_encinc' value to an accumulator (of arbitrary size), zeros '_encinc', and clears the flag. Remember to disable ints during this process, or corrupted counts will occur.
Happy to answer questions about it. Enjoy!
Rich (BB code):
;**********************************************************************
;** Rotary Quadrature Encoder **
;** By JoeyD999 (AAC) Circa 2000 **
;**********************************************************************
;** Interrupt Routine **
;** PortB.7 = Signal A **
;** PortB.6 = Signal B **
;**********************************************************************
;** On exit: **
;** _encinc = signed 8 bits **
;** = number of increments/decrements **
;** since last asynchronous read **
;** flag bit rawrdy=1 **
;**********************************************************************
;** uses inttmp, _enclst **
;**********************************************************************
;***** Interrupt Processing *****
org 0x04 ;interrupt vector
intrup movwf intw ;save context
swapf status,w
clrf status ;ensure bank 0
movwf intstat
movf pclath,w
movwf intpch
clrf pclath ;ensure this page
btfsc intcon,rbif ;port change interrupt?
goto pcint
intdone movf intpch,w ;restore context
movwf pclath
swapf intstat,w
movwf status
swapf intw,f
swapf intw,w
retfie ;return with ints enabled
;******** Port B Change Interrupt **********
pcint movf portb,w ;capture encoder bits on portb7:6
bcf intcon,rbif ;clear interrupt
movwf inttmp ;save bits
rlf inttmp,f ;move bits into encoder reg
rlf _enclst,f
rlf inttmp,f
rlf _enclst,f ;bits 3:0 have index into inc table
movlw 0x0f
andwf _enclst,w ;mask for 16 possible jumps
addwf pcl,f ;jump in table
goto none ;0 = no change
goto dec ;1 = decrement
goto inc ;2 = increment
goto none ;3 = no change
goto inc ;4 = increment
goto none ;5 = no change
goto none ;6 = no change
goto dec ;7 = decrement
goto dec ;8 = decrement
goto none ;9 = no change
goto none ;10 = no change
goto inc ;11 = increment
goto none ;12 = no change
goto inc ;13 = increment
goto dec ;14 = decrement
goto none ;15 = no change
dec decf _encinc,f ;decrement encoder counts
goto setupd
inc incf _encinc,f ;increment encoder counts
setupd bsf rawrdy ;indicate a new raw counts are ready
none goto intdone ;we are finished!
Last edited: