Hi All,
I'm struggling around rotary encoder with push button. I read the forum but not find any successfully solved example.
Here is my code:
Code:
; PIC16F1847                                 

#CONFIG ; 16FF1847.
        __config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _BOREN_OFF
        __config _CONFIG2, _PLLEN_OFF & _LVP_OFF
#ENDCONFIG

DEFINE OSC 32

OSCCON = %11110000 ;32 MHz
 
ANSELA = 0
ANSELB = 0
TRISA=%00000000
TRISB=%00000011
LATB = %00000011

Include "modedefs.bas"
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts 

INTCON=%10001000
IOCBP=%00000000         
IOCBN=%00000011         ;on change interrupt  NEGATIVE port RB.0, RB.1
IOCBF=%00000011  
       
wsave       VAR BYTE   $70 SYSTEM      ' alternate save location for W 

enc_new     VAR BYTE   bank0
enc_old     VAR BYTE   bank0
enc_counter VAR word   bank0
Flag        var BYTE   bank0

asm
INT_LIST  macro     ;IntSource,Label, Type, Resetflag?
        INT_Handler    IOC_INT, _enc,  asm,  yes
    endm
INT_CREATE          ; Creates the interrupt processor
    ;================================================
endasm
; Set variable value @ startup
Flag =        0          
enc_new =     0
enc_old =     0
enc_counter = 0           

@ INT_ENABLE IOC_INT            ; enable external (INT) interrupts

Main:
if flag=1 then
SEROUT portb.4,t9600,[#enc_counter,13]
endif
 
goto main

enc:    
asm    
    ;Read latest input from PORTB & put the value in _enc_new.
         MOVE?CB 1,_Flag
         movf    PORTB,W
         movwf  _enc_new
         ;Strip off all but the 2 MSBs in _enc_new.
         movlw    B'00000011'    ;Create bit mask (bits 1 & 0).
         andwf   _enc_new,F         ;Zero bits 5 thru 0.
         ;Determine the direction of the Rotary encoder.  
         rlf     _enc_old,F         ;left shift it into _enc_old to align bit 6 of 
                                ;_enc_old with bit 7 of _enc_new.
         movf    _enc_new,W         ;Move the contents of _enc_new to W in order to XOR.
         xorwf   _enc_old,F        ;XOR previous inputs (in _enc_old) with latest
                                ;inputs (in W) to determine CW or CCW.
 
         btfsc   _enc_old,0         ;Test bit 0 of result (in _enc_old).  Skip next line
                             ;if it is 0 (direction is CCW).
         goto    Up            ;Bit is 1 (direction is CW).  Go around Down
                             ;and increment counter.

Down
         ;Decrements _enc_counter because the rotary encoder moved CCW.
    ;Decrements _enc_counter (16 bit value), sets Z on exit.
              
        decf    _enc_counter,F      ; Decrement low byte
        incfsz  _enc_counter,W      ; Check for underflow
        incf    _enc_counter+1,F    ; Update
        decf    _enc_counter+1,F    ; Fixup
        movf    _enc_counter,W
        iorwf   _enc_counter+1,W    ; Set Z bit
        
    ;Add here code for the CCW LED if needed.
         
         goto    Continue          ;Branch around UP.
Up
         ;Increments _enc_counter because the rotary encoder moved CW.
    ;Increments _enc_counter (16 bit value), sets Z on exit.
        incfsz  _enc_counter,W      ; Add one to low byte
        decf    _enc_counter+1,F    ; No carry (negates next step)
        incf    _enc_counter+1,F    ; Add one to high byte
        movwf   _enc_counter        ; Store updated low byte back.
        iorwf   _enc_counter+1,W    ; Set Z flag
        
    ;Add here code for the CW LED if needed.
    
Continue 
         
         ;Assign the latest encoder inputs (in _enc_new) to _enc_old.
         movf     _enc_new,W
         movwf   _enc_old
         CHK?RP   IOCBF
         CLRF IOCBF
         INT_RETURN
    ;============ END OF THE ROTARY ENCODER CODE =====
endasm
The problem is, I can't get correct encoder reading. In serial monitor I can see the result but the values goes only to increment no matter if I rotate CW or CCW.
The values increment randomly. I dont know, what is the problem.
The encoder is wired with 10k pullups and debounce capacitors.
I need quic response to rotation fot that I try to use this ASM and DT interrupts metod.

Anyway If I tried another example with no ASM and Interrupts only for testing, the encoder works fine CW and CCW, increments, decrements by one just fine.

Can someone check my code and correct me what Im doing wrong.
Thanks.