You can use a timer interrupt. You can use TMR0 or just "piggyback" on Darrel's TMR1 interrupt in the SSPWM routine.
The only caveat is that the period of that interrupt must be shorter than the narrowest pulse (either high or low) that your speedometer sensor puts out.
I have written (and posted) a routine that would do what you want. Mine is written in asm, but could be written in PBP as well.
Below is a section. It measures the speed of 9 fans by watching the tachometers.
A couple of things to note -
It must be written as an ISR.
The interrupt time is determined by PRELOADH and PRELOADL.
The routine runs for an exact number of interrupts before stopping (FanClock is the counter) 1000 is the number here.
So if you interrupt at 1mSec intervals, this routine will run for 1 second before being restarted in the main loop.
To use:
Set your interrupt rate.
Determine how many counts you need to get the accuracy you want (which determines
how long you need to count and therefore, the maximum update rate of your speedometer).
If you get 1 cycle (1 high period and one low period) per foot, and you have a 50% duty cycle, then you will get 88 cycles per second with a high period of 5.6 mSec and a low period of 5.6 mSec. To account for jitter, your interrupt period would have to be 5 mSec or less. You would have 166 transitions (low->high + high -> low) in one second. If you set FanCounter to time out in .3614 seconds (say 100 counts with a 3.614 mSec update rate), the count would be in exact mph with a .3614 second update rate. Longer counting intervals and faster interrupts gives more accuracy and less jitter.
You need clear TPE before you start.
Check TPE in your main loop. If it is set, the routine has completed. Transfer the contents of the FanxCounters to another set of variables (call them FanYcounters, clear all the FanXcounters, Clear FanClock and Clear TPE. Now your main loop can read FanYcounters and display the mph, or RPM, or whatever.
You don't have to stop TMR0 on most chips to reload it. You do have to stop most of the other timers before reloading. Check your datasheet.
The routine runs for an exact number of interrupts before stopping. You need clear TPE before you start.
Code:Asm ReadTachs movff PreloadH,TMR0H ; Preload depends on clk speed movff PreloadL,TMR0L infsnz MasterClock incf MasterClock + 1 btfsc TPE,0 bra DoneForNow ;CheckFans infsnz FanClock incf FanClock + 1 movlw 0x03 - 1 ; Real value is 1000 = 0x3E8, but must have one less cpfsgt FanClock + 1 ; to compare with greater than bra FanRoutine movlw 0xE8 - 1 ; Likewise, subtract one here, too. cpfsgt FanClock bra FanRoutine bsf TPE,0 clrf FanClock clrf FanClock + 1 bra DoneForNow FanRoutine movf PORTB,0,0 movwf Temp,0 ; Save VAR so can't change between compare and save xorwf OldPortB,0,0 movwf changedB,0 movff Temp,OldPortB movf PORTC,0,0 movwf Temp,0 xorwf OldPortC,0,0 movwf changedC,0 movff Temp,OldPortC movf PORTD,0,0 movwf Temp,0 xorwf OldPortD,0,0 movwf changedD,0 movff Temp,OldPortD Fan1 btfss changedB,0 bra Fan2 infsnz Fan1Counter incf Fan1Counter+1 Fan2 btfss changedB,1 bra Fan3 infsnz Fan2Counter incf Fan2Counter+1 Fan3 btfss changedB,2 bra Fan4 infsnz Fan3Counter incf Fan3Counter+1 Fan4 btfss changedB,3 bra Fan5 infsnz Fan4Counter incf Fan4Counter+1 Fan5 btfss changedB,4 bra Fan6 infsnz Fan5Counter incf Fan5Counter+1 Fan6 btfss changedB,5 bra Fan7 infsnz Fan6Counter incf Fan6Counter+1 Fan7 btfss changedC,0 bra Fan8 infsnz Fan7Counter incf Fan7Counter+1 Fan8 btfss changedD,5 bra Fan9 infsnz Fan8Counter incf Fan8Counter+1 Fan9 btfss changedD,4 bra DoneForNow infsnz Fan9Counter incf Fan9Counter+1 DoneForNow bcf INTCON,2 ; Clear the TIMER0 interrupt flag INT_RETURN ; WAS RETFIE FAST Return from the interrupt ENDASM




Bookmarks