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