tried your code on a 500 ppr opto encoder, it seems to be good
modified to run on 16f1825, full quad decode [2000 edges / rev]
Code:
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_ON & _LVP_OFF
#ENDCONFIG
OSCCON=$70
DEFINE OSC 32
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts
' PIC 16F1825
; encoder ch A Porta.4
; encoder ch B Porta.5
enc_new VAR BYTE bank0
enc_old VAR BYTE bank0
enc_counter VAR WORD bank0
Flag var BYTE bank0
TRISA = %111111 ' Make all pins Input
trisc = %11111111 ;Make all pins Input
ANSELA=0
ANSELC=0
;SETUP IOC REGS
IOCAP = %110000 ;POS EDGE
IOCAN = %110000 ;NEG EDGE
IOCAF = 0 ;CLR INT FLAG
intcon.3 = 1 ;iocie
asm
INT_LIST macro ; IntSource, Label, Type, Resetflag?
INT_Handler IOC_INT, _enc, ASM, NO
endm
INT_CREATE ; Creates the interrupt processor
endasm
;debug --------------------------
TRISA.0 = 0
lata.0=1
pause 2000 ;debug
serout2 PORTa.0,84, ["ready v3",13,10 ] ;debug
;debug ------------------------------------
; Set variable value @ startup
Flag = 0
enc_new = 0
enc_old= 0
enc_counter = 0
@ INT_ENABLE IOC_INT
Main_Loop:
if Flag = 1 then
serout2 PORTa.0,84, [#enc_counter,13,10 ]
Flag = 0
endif
goto Main_Loop
end
enc:
asm
;Read latest input from PORTA & put the value in _enc_new.
MOVE?CB 1,_Flag
CHK?RP PORTA
movf PORTA,W
RST?RP
movwf _enc_new
;Strip off all but the 2 MSBs in _enc_new.
movlw B'00110000' ;Create bit mask (bits 7 & 6).
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,5 ;Test bit 5 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 IOCAF
CLRF IOCAF
INT_RETURN
;============ END OF THE ROTARY ENCODER CODE =====
endasm
Bookmarks