Code:
'************************************************
'* Name : mod_ENCDRdisp.BAS
'* Author : Michael St. Pierre
'* Notice : Copyright (c) 2005 Mytek Controls
'* : Free For All To Use
'* Date : 06/14/2005
'* Version : 1.0
'* Notes : MEL PicBasic Pro Rotary Encoder Display Routine
'* : Includes 8-bit Prescaler
'************************************************
DEFINE OSC 40
DEFINE INTHAND myint
' Device = PIC18Fxxx
'================================================
' Equates
'================================================
ENCA var PORTC.x ' use any 2 schmidt trigger inputs with 10K pull-ups
ENCB var PORTC.x
encoder var byte
auxenc var byte
Ecount var byte[6] bankA
prescale var byte
psvalue var byte
direnc var bit
loopcount var byte
periodH con $FE
periodL con $0B
ascii var byte
'Variables for saving state in interrupt handler
fsave var word bankA system ' Saves FSR0
Goto Start ' Jump past interrupt routine
'================================================
' Interrupt Handler (High Priority)
' Rotary Encoder w/precaler and 6 digit up/down counter
'================================================
asm
myint
; save the FSR value because it gets changed below
movf FSR0L, W
movwf fsave
movf FSR0H, W
movwf fsave+1
; Main Interrupt routine begins here
; Timer1 set-up as 20 Khz counter (.00005 sec period)
bcf _TMR1ON ; turn OFF Timer1 for counter load
movlw _periodH
movwf TMR1H ; load high byte of period counter
movlw _periodL
movwf TMR1L ; load low byte of period counter
bcf _TMR1IF ; clear Timer1 IRQ Flag
bsf _TMR1ON ; turn Timer1 back ON
;check rotary encoder inputs (@20 Khz rate)
chk_encoder
clrf _auxenc
btfsc _ENCA
bsf _auxenc,0
btfsc _ENCB
bsf _auxenc,1
movf _auxenc, W
xorwf _encoder, F
rrf _auxenc, F
rlf _encoder, F
rrf _auxenc, F
rlf _encoder, F
btfsc _encoder,2
goto encoder_up
chk_down
btfsc _encoder,3
goto encoder_down
goto restore
encoder_up
btfss _encoder,3
bsf _direnc
btfsc _encoder,3
goto chk_down
goto countup
encoder_down
btfss _encoder,2
bcf _direnc
btfsc _encoder,2
goto restore
goto countdown
;Encoder 6 Digit Counter w/PreScaler - Count Up
countup
;prescaler
movf _psvalue, W ; retrieve prescaler value and...
subwf _prescale, W ; compare to prescale count
btfsc STATUS, Z ; Have we finished prescaling?
goto preupdone ; Yes! Go begin actual count
incf _prescale, F ; Else keep incrementing prescale count and
goto restore ; Leave!
preupdone
clrf _prescale ; Set-up for next prescale event
clrf _loopcount
LFSR FSR0, _Ecount ; set counter base address
inc_loop
movlw d'9'
subwf INDF0, W
btfsc STATUS, Z ; Have we hit top for this digit?
goto nextdigit ; Yes, go to next!
incf INDF0, F ; else keep incrementing it, and...
goto enc_exit ; Leave!
nextdigit
clrf POSTINC0 ; (clear INDF and increment FSR)
incf _loopcount, F
movlw d'6'
subwf _loopcount,W
btfss STATUS, Z ; Have we checked all 6 digits?
goto inc_loop ; No go to next!
goto enc_exit
;Encoder 6 Digit Counter w/PreScaler - Count Down
countdown
;prescaler
movf _prescale, W ; retrieve prescaler value
btfsc STATUS, Z ; Have we finished prescaling?
goto predowndone ; Yes! Go begin actual count
decf _prescale, F ; Else keep decrementing prescale count and
goto restore ; Leave!
predowndone
movf _psvalue, W
movwf _prescale ; Set-up for next prescale event
clrf _loopcount
LFSR FSR0, _Ecount ; set counter base address
dec_loop
movf INDF0, W ; retrieve digit[x]
bnz dec_digit ; Are we at the bottom for this digit?
movlw d'9' ; Yes, roll it over!
movwf POSTINC0 ; (move w = 9 to INDF and increment FSR)
incf _loopcount, F
movlw d'6'
subwf _loopcount, W
btfss STATUS, Z ; Have we checked all 6 digits?
goto dec_loop ; No go to next!
goto enc_exit
dec_digit
decf INDF0, F ; Not at bottom, keep decrementing it, and...
goto enc_exit ; leave!
enc_exit
bsf _AUTOdispNEW ; flag that encoder value has changed
;restore registers
restore
movf fsave, W
movwf FSR0L
movf fsave+1, W
movwf FSR0H
retfie FAST
endasm
'================================================
' Program Start
'================================================
Start:
Clear
' Set-up Interrupts and Timers
TMR1H = periodH ' Pre-load Timer1 High Byte
TMR1L = periodL ' Pre-load Timer1 Low Byte
T1CON = %000001 ' Set Timer1: IntCLK SRC,Pre 1:1, - Timer ON
TMR1IF = 0 ' Clear Timer1 IRQ Overflow Flag
TMR1IE = 1 ' Enable Timer1 IRQ on Overflow
TMR1IP = 1 ' Timer 1 set as high priority interrupt
IPEN = 1 ' Enable priority levels on interrupts
INTCON = %11000000 ' Enable all interrupts!
Pause 100
Gosub reset_enc ' initialize encoder
psvalue = 0 ' initialize prescaler
' psvalue = 0 - no prescaling -
' psvalue = 1 divide by 2
' psvalue = 2 divide by 3
' psvalue = 99 divide by 100
' Main Program Loop Begins Here
mainloop
If AUTOdispNEW = 1 Then Gosub ENCDRdisp
'--------------------------------------------
' your mainloop code goes here
'--------------------------------------------
Goto mainloop
ENCDRdisp:
' display direction indicator
If direnc = 1 Then
ascii = "+" 'direction = UP
Else
ascii = "-" 'direction = down
Endif
Gosub printascii
' display distance
For x = 5 To 0 Step-1
ascii = (Ecount DIG x) + $30
Gosub printascii
Next x
Return
' Reset "ZERO" Encoder Display
reset_enc:
AUTOdispNEW = 1
prescale = 0
For x = 0 To 5
Ecount[x] = 0
Next x
Return
' Print ascii characters
printascii:
' your ascii print/display routine goes here
Return
End
Please excuse the lack of comments on the chk_encoder part of the routine. It was a public domain example that I pasted into my code ( I wish I could remember the author).
Bookmarks