Another PIC Trick -- Quadrature Rotary Encoders

Discussion in 'Embedded Systems and Microcontrollers' started by joeyd999, Jan 5, 2012.

  1. joeyd999

    Thread Starter AAC Fanatic!

    Jun 6, 2011
    2,673
    2,715
    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!

    Code ( (Unknown Language)):
    1.  
    2. ;**********************************************************************
    3. ;** Rotary Quadrature Encoder                                        **
    4. ;** By JoeyD999 (AAC) Circa 2000                                     **
    5. ;**********************************************************************
    6. ;** Interrupt Routine                                                **
    7. ;** PortB.7 = Signal A                                               **
    8. ;** PortB.6 = Signal B                                               **
    9. ;**********************************************************************
    10. ;** On exit:                                                         **
    11. ;**   _encinc = signed 8 bits                                        **
    12. ;**           = number of increments/decrements                      **
    13. ;**             since last asynchronous read                         **
    14. ;**   flag bit rawrdy=1                                              **
    15. ;**********************************************************************
    16. ;**   uses inttmp, _enclst                                           **
    17. ;**********************************************************************    
    18.  
    19. ;***** Interrupt Processing *****
    20.  
    21.     org 0x04            ;interrupt vector
    22.  
    23. intrup  movwf   intw            ;save context
    24.     swapf   status,w
    25.     clrf    status          ;ensure bank 0
    26.     movwf   intstat
    27.     movf    pclath,w
    28.     movwf   intpch
    29.     clrf    pclath          ;ensure this page
    30.  
    31.     btfsc   intcon,rbif     ;port change interrupt?
    32.     goto    pcint
    33.  
    34. intdone movf    intpch,w        ;restore context
    35.     movwf   pclath
    36.     swapf   intstat,w
    37.     movwf   status
    38.     swapf   intw,f
    39.     swapf   intw,w
    40.  
    41.     retfie              ;return with ints enabled
    42.  
    43. ;******** Port B Change Interrupt **********
    44.  
    45. pcint   movf    portb,w         ;capture encoder bits on portb7:6
    46.     bcf intcon,rbif     ;clear interrupt
    47.     movwf   inttmp          ;save bits
    48.  
    49.     rlf inttmp,f        ;move bits into encoder reg
    50.     rlf _enclst,f
    51.     rlf inttmp,f
    52.     rlf _enclst,f       ;bits 3:0 have index into inc table
    53.  
    54.     movlw   0x0f
    55.     andwf   _enclst,w       ;mask for 16 possible jumps
    56.     addwf   pcl,f           ;jump in table
    57.  
    58.     goto    none            ;0 = no change
    59.     goto    dec         ;1 = decrement
    60.     goto    inc         ;2 = increment
    61.     goto    none            ;3 = no change
    62.    
    63.     goto    inc         ;4 = increment
    64.     goto    none            ;5 = no change
    65.     goto    none            ;6 = no change
    66.     goto    dec         ;7 = decrement
    67.  
    68.     goto    dec         ;8 = decrement
    69.     goto    none            ;9 = no change
    70.     goto    none            ;10 = no change
    71.     goto    inc         ;11 = increment
    72.  
    73.     goto    none            ;12 = no change
    74.     goto    inc         ;13 = increment
    75.     goto    dec         ;14 = decrement
    76.     goto    none            ;15 = no change
    77.  
    78. dec decf    _encinc,f       ;decrement encoder counts
    79.     goto    setupd
    80.  
    81. inc incf    _encinc,f       ;increment encoder counts
    82.  
    83. setupd  bsf rawrdy          ;indicate a new raw counts are ready
    84.  
    85. none    goto    intdone         ;we are finished!
    86.  
     
    Last edited: Jan 5, 2012
    MaxHeadRoom and SPQR like this.
Loading...