Help with Timer1

// Fast Timer
// Written by John Wasser
//
// Returns the current time in 16ths of a microsecond.
// Overflows every 268.435456 seconds.

// Note: Since this uses Timer1, Pin 9 and Pin 10 can't be used for
// analogWrite().

void StartFastTimer()
{
noInterrupts (); // protected code
// Reset Timer 1 to WGM 0, no PWM, and no clock
TCCR1A = 0;
TCCR1B = 0;

TCNT1 = 0; // Reset the counter
TIMSK1 = 0; // Turn off all Timer1 interrupts

// Clear the Timer1 Overflow Flag (yes, by writing 1 to it)
// so we don't get an immediate interrupt when we enable it.
TIFR1 = _BV(TOV1);

TCCR1B = _BV(CS10); // start Timer 1, no prescale
// Note: For longer intervals you could use a prescale of 8
// to get 8 times the duration at 1/8th the resolution (1/2
// microsecond intervals). Set '_BV(CS11)' instead.

TIMSK1 = _BV(TOIE1); // Timer 1 Overflow Interrupt Enable
interrupts ();
}

volatile uint16_t Overflows = 0;

ISR(TIMER1_OVF_vect)
{
Overflows++;
}

unsigned long FastTimer()
{
unsigned long currentTime;
uint16_t overflows;

noInterrupts();
overflows = Overflows; // Make a local copy

// If an overflow happened but has not been handled yet
// and the timer count was close to zero, count the
// overflow as part of this time.
if ((TIFR1 & _BV(TOV1)) && (TCNT1 < 1024))
overflows++;

currentTime = overflows; // Upper 16 bits
currentTime = (currentTime << 16) | TCNT1;
interrupts();

return currentTime;
}

// Demonstration of use
#if 1
void setup()
{
Serial.begin(115200);
while (!Serial);
StartFastTimer();
}

void loop()
{
static unsigned long previousTime = 0;
unsigned long currentTime = FastTimer();

Serial.println(currentTime - previousTime);
previousTime = currentTime;

delay(100);
}
#endif

1 Like