Hello,

I know this is an old thread but I have reached the extent of my knowledge with PBP. I have been testing the code published by several forum members and the code works wonderful. Using the asm interrupts provides very fast response and no missed counts. The issue I have is trying to display the results on LCD in 4 digit result (xx.xx). I'm using the following hardware:

16F876 @ 20MHz
US digital S4T-360 (360 CPR)
2x16 LCD connected to PortA

I'm using the encoder to measure angles from a center position (12 o'clock). It can turn +/- 90 degrees. I need to display the results as +/- any value between 0 and 90 such as 46.15 or -58.23 (cw,ccw respectively).

Since the count value is one byte, I can't figure out a way to get greater resolution for the count. I'm very new to programming period!!! I realize I have a lot to learn and I will continue to learn.
I've tried using sdec enc_Count/10, enc_count//10 in the LCD lines but the results are not giving me what I need.

Maybe I'm missing something really simple and I hope someone can point me in the right direction.

Here is the code I'm using:


Code:
'Read Quadrature Encoder and display value on LCD. for pic16f876a

'setup PIC Config Fuses
    @ Device pic16F876A, HS_OSC, BOD_OFF, PWRT_ON, WDT_OFF, PROTECT_OFF

'************************ DEFINES HERE *************************************
DEFINE OSC 20               ' set to 20mhz
DEFINE LCD_DREG PORTA       ' Set Data Registers port
DEFINE LCD_DBIT 0           ' Set starting data bit
DEFINE LCD_RSREG PORTB      ' Set LCD RS Port
DEFINE LCD_RSBIT 1          ' Set LCD RS Bit
DEFINE LCD_EREG PORTB       ' Set LCD Enable Port
DEFINE LCD_EBIT 2           ' Set LCD Enable Bit
DEFINE LCD_BITS 4           ' Set LCD 4bit Mode
DEFINE LCD_LINES 2          ' Set number of LCD Lines
DEFINE LCD_COMMANDUS 2000   ' Set Command Delay time in uS
DEFINE LCD_DATAUS 60        ' Set Data delay time in uS 

clear                       'clear out variables

'*********************** CHIP REGISTER SETUP *******************************

ADCON0 = 7              ' turn off analog porta, set to digital IO
ADCON1 = 7              '
CMCON =  7              ' Turn off Port A Comparator
TRISA = 0               ' output ports
TRISB = %11000001       ' set input and output ports
TRISC = 0               ' output ports

'************************ PROGRAM VARIABLES HERE ***************************

symbol led = portc.2        ' status led
symbol led2 = portc.0       ' status led2
symbol lcdbkl = portc.7     ' lcd pannel backlight
symbol sw1 = portb.0        ' encoder switch

enc_old VAR BYTE
enc_new VAR BYTE
enc_tmp var byte
enc_counter VAR WORD
enc_counter_old VAR WORD
enc_scaler var word




'*********************** ASSEMBLY INTERUPT VARIABLES ***********************
wsave   var     byte $20 system
wsave1  var     byte $a0 system  ' Necessary for devices with RAM in bank1
wsave2  var     byte $120 system ' Necessary for devices with RAM in bank2
wsave3  var     byte $1a0 system ' Necessary for devices with RAM in bank3
ssave   var     byte bank0 system
psave   var     byte bank0 system     

goto start			'skip over interupt handler
'*********************** ASSEMBLY INTERUPT HANDLER *************************

define  INTHAND myint
Asm
       
myint 
	; Save W, STATUS and PCLATH registers
	; Not Necessary for Chips with >2k of Codespace
       ; movwf   wsave
       ; swapf   STATUS, W
       ; clrf    STATUS
       ; movwf   ssave
       ; movf    PCLATH, W
       ; movwf   psave  
         



	;====== BEGINNING OF THE ROTARY ENCODER CODE ========
	;The Rotary Encoder is connected to PORTB  
	;The A signal of the encoder connected to the PIN portB.7
	;The B signal of the encoder connected to the PIN portB.6
	;
	;The 4 variables used are declared in the PicBasic code.
	;
	;	enc_new VAR BYTE
	;	enc_old VAR BYTE
	;       enc_tmp VAR BYTE
	;	enc_counter VAR WORD
	;
	;================================================
		
	   ;Read latest input from PORTB & put the value in _enc_new.
     	movf    PORTB,W
     	movwf  _enc_new

     	;Strip off all but the 2 MSBs in _enc_new.
     	movlw	0xc0    	     ;Create bit mask (bits 7 & 6). b'11000000' ?
     	andwf   _enc_new,F       ;Zero bits 5 thru 0.

        ;check to see if encoder has moved
        movf    _enc_old,W         ;move enc_old to W
        movwf   _enc_tmp           ;put W to enc_tmp
        movf    _enc_new,W         ;move enc_new to W for XOR
        xorwf   _enc_tmp,F         ;XOR enc_tmp to detect encoder movement
        btfsc   _enc_tmp,7         ;if bit is clear, encoder moved.
        goto    Continue           ;no movement exit isr

     	;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,7     	 ;Test bit 7 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.
     	bsf     _led		    ;turn on led
     	
     	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.
	   bsf     _led2		    ;turn on led
	
Continue     	
     	;Assign the latest encoder inputs (in _enc_new) to _enc_old.
     	movf 	_enc_new,W
     	movwf   _enc_old

        ; Restore saved registers
        movf    psave, W
        movwf   PCLATH
        swapf   ssave, W
        movwf   STATUS
        swapf   wsave, F
        swapf   wsave, W
        bcf     INTCON, RBIF		  ; Clear the Interupt Flag
        RETFIE                 	  	  ; Return from interrupt
endasm

'***************************************************************************
'************************* PROGRAM STARTS HERE *****************************
'***************************************************************************

START:              ' Main Program starts here

LCDOUT $FE,1		'Init The LCD
pause 500		    'wait for LCD to start 

lcdout $FE,1,"ENCODER"	    'display splash screen
LCDOUT $FE,$C0," TEST "       
high lcdbkl                 ' turn on backlight


'************************** SET DEFAULT SETTINGS HERE **********************
pause 1000		    ' just wait a bit to read splash screen
enc_counter = 0	' set default encoder value
enc_counter_old = 0	

lcdout $FE,1,"ENCODER"  ' change display
lcdout $fe,$C0, DEC5 enc_counter
INTCON = %10001000      ' Enable PortB Change Interupts  


'************************** TESTING ROUTINES HERE **************************
test:
            if  enc_counter <> enc_counter_old then 'see if value has changed
                enc_counter_old = enc_counter		'move new value to old
           
             ' Here is were I struggle.....
             '*********************************************************************************
                lcdout $fe,$C0, SDEC2 enc_counter/10, ".", SDEC2 enc_counter//10     	'display enc_counter value
             '*********************************************************************************

                low led		                        'turn off CCW led
                low led2	                        'turn off CW led
            endif
goto test
Thank you in advance,

cbrun17