' ========================================================================= ' ' File...... Tachometer.SXB ' Purpose... ' Author.... Jon Williams, EFX-TEK ' Copyright (c) 2008 EFX-TEK ' Some Rights Reserved ' -- see http://creativecommons.org/licenses/by/3.0/ ' E-mail.... jwilliams@efx-tek.com ' Started... ' Updated... 08 JUL 2008 ' ' ========================================================================= ' ------------------------------------------------------------------------- ' Program Description ' ------------------------------------------------------------------------- ' ------------------------------------------------------------------------- ' Conditional Compilation Symbols ' ------------------------------------------------------------------------- ' ------------------------------------------------------------------------- ' Device Settings ' ------------------------------------------------------------------------- DEVICE SX28, OSCXT2, TURBO, STACKX, OPTIONX, BOR42 FREQ 50_000_000 ID "Tach" ' ------------------------------------------------------------------------- ' I/O Pins ' ------------------------------------------------------------------------- RpmIn PIN RB.0 INPUT SCHMITT ' DMdm DAVE dave (i added the SCHMITT) maybe try cmos 50% vdd Segs PIN RC OUTPUT ' display segments (anodes) DigCtrl PIN RA OUTPUT ' digit control (cathodes) ' ------------------------------------------------------------------------- ' Constants ' ------------------------------------------------------------------------- MaxDigit CON 4 ' 4-digit display Yes CON 1 No CON 0 Blank CON %00000000 Dash CON %01000000 ' segment g Line CON %00001000 ' segment d ' ------------------------------------------------------------------------- ' Variables ' ------------------------------------------------------------------------- flags VAR Byte isrFlag VAR flags.0 overFlow VAR flags.1 done VAR flags.2 pWidth0 VAR Word ' pulse measurements pWidth1 VAR Word rpm VAR Word dividendMSW VAR Word ' for 32-bit divide dividendLSW VAR Word tmpB1 VAR Byte ' for subs/funcs tmpB2 VAR Byte tmpW1 VAR Word digits VAR Byte (5) ' extracted digits display VAR Byte (5) ' multiplexed segments digPntr VAR Byte ' digit pointer ' ========================================================================= INTERRUPT 100_000 ' ========================================================================= Mark_ISR: isrFlag = 1 ' mark the ISR Next_Digit: INC digPntr ' point to next digit IF digPntr = MaxDigit THEN ' check pointer digPntr = 0 ' wrap if needed ENDIF Update_Segs: Segs = %00000000 ' blank segments READ DigMap + digPntr, DigCtrl ' update digit control Segs = display(digPntr) ' output new segments ISR_Exit: RETURNINT ' ------------------------------------------------------------------------- ' Subroutine / Function Declarations ' ------------------------------------------------------------------------- DELAY_MS SUB 1, 2 ' replaces PAUSE MEASURE_LO FUNC 2 ' measure 1->0->1 pulse MEASURE_HI FUNC 2 ' measure 0->1->0 pulse VAL_TO_ARRAY SUB 2, 3 ' extract digits to array ' ========================================================================= PROGRAM Start ' ========================================================================= Start: DigCtrl = %11111111 ' segs off to start PLP_B = %00000001 ' pull-up unused pins PUT display, Blank, Blank, Blank, Blank ' blank display Main: pWidth0 = MEASURE_LO ' measure pulses pWidth1 = MEASURE_HI pWidth0 = pWidth0 + pWidth1 ' convert to period IF C = 1 THEN ' rollover? PUT display, Blank, Dash, Dash, Blank ' indicate low rpm GOTO Loop_Pad ENDIF IF pWidth0 < 601 THEN ' > 9999 rpm? PUT display, Dash, Dash, Dash, Dash ' indicate high rpm GOTO Loop_Pad ENDIF ' 32-bit divide by Bean (?) Convert_To_RPM: dividendMSW = $005B ' dividend = 6_000_000 dividendLSW = $8D80 rpm = 1 overflow = 0 DO done = rpm.15 rpm = rpm << 1 IF overflow = 1 THEN rpm.0 = 1 dividendMSW = dividendMSW - pWidth0 ELSE IF dividendMSW >= pWidth0 THEN rpm.0 = 1 dividendMSW = dividendMSW - pWidth0 ENDIF ENDIF overflow = dividendMSW.15 dividendMSW = dividendMSW << 1 dividendMSW.0 = dividendLSW.15 dividendLSW = dividendLSW << 1 LOOP UNTIL done = Yes rpm = rpm << 1 rpm.0 = overflow IF dividendMSW >= pWidth0 THEN rpm.0 = 1 ENDIF Update_Display: VAL_TO_ARRAY rpm, @digits(0) ' extract digits FOR tmpB1 = 0 TO 4 READ SegMap + digits(tmpB1), display(tmpB1) ' convert to segment map NEXT No_LZ: FOR tmpB1 = 4 TO 0 STEP -1 IF digits(tmpB1) > 0 THEN EXIT ELSE display(tmpB1) = 0 ' remove leading zero ENDIF NEXT Loop_Pad: DELAY_MS 200 ' let display settle GOTO Main ' ------------------------------------------------------------------------- ' Subroutine / Function Code ' ------------------------------------------------------------------------- ' Use: DELAY_MS duration ' -- replaces PAUSE SUB DELAY_MS IF __PARAMCNT = 1 THEN tmpW1 = __PARAM1 ' byte parameter ELSE tmpW1 = __WPARAM12 ' word parameter ENDIF DO WHILE tmpW1 > 0 ' while ms left tmpB1 = 100 ' load 1ms timer DO WHILE tmpB1 > 0 ' while timer running ASM CLRB isrFlag ' clear flag JNB isrFlag, $ ' wait for next ENDASM DEC tmpB1 ' update timer LOOP DEC tmpW1 ' update ms count LOOP ENDSUB ' ------------------------------------------------------------------------- ' Use: result = MEASURE_HI ' -- measures high-going pulse on RpmIn pin ' -- measurement is in 10 uS (ISR rate) units FUNC MEASURE_HI tmpW1 = 0 ' clear measurement ASM JB RpmIn, $ ' wait for low JNB RpmIn, $ ' wait for 0 -> 1 ENDASM DO WHILE RpmIn = 1 ' loop while high ASM CLRB isrFlag ' clear flag JNB isrFlag, $ ' wait for next ENDASM INC tmpW1 ' update timing IF tmpW1 = 0 THEN EXIT ' abort on roll-over LOOP RETURN tmpW1 ENDFUNC ' ------------------------------------------------------------------------- ' Use: result = MEASURE_LO ' -- measures low-going pulse on RpmIn pin ' -- measurement is in 10 uS (ISR rate) units FUNC MEASURE_LO tmpW1 = 0 ' clear measurement ASM JNB RpmIn, $ ' wait for high JB RpmIn, $ ' wait for 1 -> 0 ENDASM DO WHILE RpmIn = 0 ' loop while low ASM CLRB isrFlag ' clear flag JNB isrFlag, $ ' wait for next ENDASM INC tmpW1 ' update timing IF tmpW1 = 0 THEN EXIT ' abort on roll-over LOOP RETURN tmpW1 ENDFUNC ' ------------------------------------------------------------------------- ' Use: VAL_TO_ARRAY value, pntr ' -- extracts digits from value, moves to array at pntr ' -- array(0) holds ones; array(4) holds 10_000s SUB VAL_TO_ARRAY IF __paramcnt = 2 THEN tmpW1 = __PARAM1 ' value tmpB1 = __PARAM2 ' pointer to array ELSE tmpW1 = __WPARAM12 tmpB1 = __PARAM3 ENDIF FOR tmpB2 = 1 TO 5 ' five digits tmpW1 = tmpW1 / 10 ' extract 1s digit __RAM(tmpB1) = __REMAINDER ' move to array INC tmpB1 ' point to next element NEXT ENDSUB ' ------------------------------------------------------------------------- ' User Data ' ------------------------------------------------------------------------- SegMap: ' 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 DigMap: ' digit select map DATA %11111110 DATA %11111101 DATA %11111011 DATA %11110111