I do it this way
enc pins must be sequential and on same port
both enc pins must be able to generate an interrupt (ioc on neg and pos edge is best , ioc, rac,rbc on neg or pos edge will work as will int0 int1)
enc pins must be pulled up (10k) and have 0.1uF filter caps
I have an asm version that's 100 bytes smaller and has about 1 tenth of the irq latency and is much faster too
Code:
'****************************************************************
'* Name : rotary encoder.BAS *
'* Author : richard *
'* Notice : Copyright (c) 2013 *
'* : All Rights Reserved *
'* Date : 9/4/2013 *
'* Version : 1.0 16f1825 *
'* Notes : enca porta.2 encb porta.3 *
'* : note mclr disabled ,full quad decode *
'****************************************************************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_ON & _LVP_OFF
#ENDCONFIG
include "dt_ints-14.bas"
include "REENTERPBP.bas"
asm
INT_LIST macro
INT_HANDLER IOC_INT, _enc_isr,pbp,NO
endm
INT_CREATE
ENDASM
DEFINE OSC 32
OSCCON=$70
ANSELA=0
OPTION_REG.6=0
ev VAR BYTE bank0
cnt VAR WORD bank0
TMP VAR BYTE bank0
enca VAR porta.2
encb VAR porta.3
TRISA = 111110
lata.0=1
IOCAP=12 ;enca porta.2 encb porta.3 pos edge trigger
IOCAN=12 ;enca porta.2 encb porta.3 neg edge trigger
pause 4000
serout2 PORTA.0,84,[ "ready",13,10]
IOCAF=0
INTCON=$C8
mainloop:
serout2 PORTA.0,84,[13,10, "C",#CNT]
pause 1000
goto mainloop
enc_isr:
ev=ev<<2 ;shift last reading into position
ev=ev|((porta&12)>>2) ;read enc pins 2,3 mask off others then combine this reading with last reading
LOOKUP (ev&$f),[0,255, 1, 0, 1, 0, 0, 255, 255, 0, 0, 1, 0, 1, 255, 0],tmp ;lookup the decision matrix
if tmp then ; decide to inc , dec or ignore
if tmp.7 then
cnt=cnt-1
else
cnt=cnt+1
endif
endif
intcon.0=0 ; clean up and exit
iocaf=0
@ INT_RETURN
Bookmarks