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:
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.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 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.




Bookmarks