| SX/B Example: Quadrature Encoder Input | Examples Index |
' =========================================================================
'
' File...... ENCODER.SXB
' Purpose... Grayhill 25LB10-Q Encoder Demo
' Author.... (c) Parallax, Inc. -- All Rights Reserved
' E-mail.... support@parallax.com
' Started...
' Updated... 05 JUL 2006
'
' =========================================================================
' -------------------------------------------------------------------------
' Program Description
' -------------------------------------------------------------------------
'
' Reads a Grayhill 25LB10-Q quadrature encode and displays a value on
' three 7-segment LEDs. When the value is zero, the display reads "OFF."
' Reading the encoder and multiplexing the displays is handled in the
' "background" with an ISR.
' -------------------------------------------------------------------------
' Device Settings
' -------------------------------------------------------------------------
DEVICE SX28, OSC4MHZ, TURBO, STACKX, OPTIONX
FREQ 4_000_000
ID "ENCODER"
' -------------------------------------------------------------------------
' IO Pins
' -------------------------------------------------------------------------
EncPort VAR RA ' encoder port
TRIS_Enc VAR TRIS_A
Cathodes VAR RB ' LED cathodes
TRIS_Cath VAR TRIS_B
Anodes VAR RC ' LED anodes
TRIS_Ano VAR TRIS_C
' -------------------------------------------------------------------------
' Constants
' -------------------------------------------------------------------------
Blank CON %00000000 ' all segs off
Ltr_O CON %00111111 ' pattern for "O"
Ltr_F CON %01110001 ' pattern for "F"
Yes CON 1
No CON 0
MaxVal CON 100
' -------------------------------------------------------------------------
' Variables
' -------------------------------------------------------------------------
display VAR Byte(3) ' multiplexed segments
digPntr VAR Byte ' digit pointer
digLimit VAR Byte ' 0 - 2
flags VAR Byte
newVal VAR flags.0
encCheck VAR Byte
encOld VAR Byte ' previous encoder bits
encNew VAR Byte ' new encoder bits
encValue VAR Byte ' encoder value
tmpB1 VAR Byte
tmpB2 VAR Byte
tmpB3 VAR Byte
' -------------------------------------------------------------------------
INTERRUPT
' -------------------------------------------------------------------------
' Runs every 64 uS @ 4 MHz (no prescaler)
ISR_Start:
encNew = EncPort & %00000011 ' get econder bits
tmpB3 = encOld XOR encNew ' test for change
IF tmpB3 > 0 THEN ' change?
encOld = encOld << 1 ' adjust old bits
encOld = encOld XOR encNew ' test direction
IF encOld.1 = 1 THEN
IF encValue < MaxVal THEN ' if max, no change
INC encValue ' increase value
newVal = 1 ' alert "foreground"
ENDIF
ELSE
IF encValue > 0 THEN ' if 0, no change
DEC encValue ' decrease value
newVal = 1 ' alert "foreground"
ENDIF
ENDIF
encOld = encNew ' save last input
ENDIF
Update_Display:
INC digPntr ' point to next digit
IF digPntr = digLimit THEN ' update digit
digPntr = 0 ' wrap if needed
ENDIF
Anodes = Blank ' blank display
READ DigCtrl + digPntr, Cathodes ' select display element
Anodes = display(digPntr) ' output new digit segs
ISR_Exit:
RETURNINT
' =========================================================================
PROGRAM Start
' =========================================================================
' -------------------------------------------------------------------------
' Subroutine Declarations
' -------------------------------------------------------------------------
UPDATE_ABUF SUB 0 ' update anode buffer
' -------------------------------------------------------------------------
' Program Code
' -------------------------------------------------------------------------
Start:
Anodes = Blank ' clear LEDs
TRIS_Ano = %00000000 ' make anode ctrl outputs
Cathodes = %111 ' all digits off
TRIS_Cath = %11111000 ' make cath ctrl outputs
encNew = EncPort & %00000011 ' read encoder pos
encOld = encNew ' copy
encValue = 0 ' clear value
UPDATE_ABUF ' update display char buf
OPTION = $88 ' interrupt, no prescaler
Main:
DO
IF newVal = Yes THEN ' check flag
UPDATE_ABUF ' refresh display buffer
ENDIF
LOOP
' -------------------------------------------------------------------------
' Subroutine Code
' -------------------------------------------------------------------------
UPDATE_ABUF:
IF encValue = 0 THEN
PUT display(0), Ltr_F, Ltr_F, Ltr_O ' if 0, show "OFF"
digLimit = 3
ELSE
digLimit = 1 ' at least one digit
IF encValue > 9 THEN ' into 10s?
INC digLimit ' -- yes, show another digit
ENDIF
IF encValue > 99 THEN ' into 100s?
INC digLimit ' -- yes, show another digit
ENDIF
tmpB1 = encValue ' convert value to segments
tmpB2 = tmpB1 / 100
tmpB1 = __REMAINDER
READ SegMaps + tmpB2, display(2)
tmpB2 = tmpB1 / 10
tmpB1 = __REMAINDER
READ SegMaps + tmpB2, display(1)
READ SegMaps + tmpB1, display(0)
ENDIF
newVal = No ' clear flag
RETURN
' =========================================================================
' User Data
' =========================================================================
SegMaps: ' segments maps
' .gfedcba
DATA %00111111 ' 0
DATA %00000110 ' 1
DATA %01011011 ' 2
DATA %01001111 ' 3
DATA %01100110 ' 4
DATA %01101101 ' 5
DATA %01111101 ' 6
DATA %00000111 ' 7
DATA %01111111 ' 8
DATA %01100111 ' 9
DATA %01110111 ' A
DATA %01111100 ' b
DATA %00111001 ' C
DATA %01011110 ' d
DATA %01111001 ' E
DATA %01110001 ' F
DigCtrl:
DATA %11111110 ' column 0 on
DATA %11111101
DATA %11111011