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