Timer1 firing immediately I'm trying to use Timer1 to get fired once a certain event occurs (about 1ms after the event). Using the timer to get a periodic interrupt works fine, but the very first interrupt fires immediately, rather than after the time I want it.

#include &lt;Arduino.h&gt;

void setup() {
  Serial.begin(115200);
  Serial.println("start");
}

#define ENTRIES 5
long stack[ENTRIES+1];
int ctr = 0;

ISR(TIMER1_OVF_vect) {
  cli();
  TCNT1 = 50000;

  // if (micros() - stack[0] &lt; 500) return; // work around guard would skip stray 1st interrupt

  stack[ctr++] = micros();

  if (ctr &gt; ENTRIES)
    TIMSK1 &amp;= ~(1 &lt;&lt; TOIE1);

  sei();
}

void loop() {
  if (ctr &gt; ENTRIES) {
    for (int i = 0; i &lt; ENTRIES-1; i++) {
      Serial.print(i);
      Serial.print(": ");
      Serial.println(stack[i+1] - stack[i]);
    }
    ctr = 0;
  }

  if (!Serial.available()) return;
  char c = Serial.read();
  if (c == 't') {
    Serial.println("testing");

    stack[0] = micros();
    ctr = 1;
    cli(); 

    TCNT1 = 64000; // tick in around 1ms
    TCCR1A = 0;
    TCCR1B = (1 &lt;&lt; CS10); // no prescaler
    TIMSK1 |= (1 &lt;&lt; TOIE1); // enable timer overflow interrupt

    sei();
  }
}


When you enter t on the console it enables the interrupt and - unexpectedly - the timer fires at once. The next one comes after 1ms. A sample output looks like

start
testing
0: 8
1: 980
2: 980
3: 980
testing
0: 8
1: 980
2: 980
3: 980


Uncommenting the guard yields

start
testing
0: 988
1: 972
2: 976
3: 976


How can I modify my code (except setting a guard in the beginning of the ISR) so it is triggered once AFTER 1ms.
Interrupt flags are set even without interrupt enable flags, so there is pending overflow that you didin't cleared. And guess what happens after enabling TOIE1 flag. It gets handled by ISR. That's on behalf of Arduino's analogWrite() PWM outputs (all timers are up and running in 8bit mode and 1.024ms period).

Btw global interrupts are disabled and reenabled inside of ISR handler by hardware so you shouldn't have cli() and sei() in it.

Also there is another issue - counter mode is preset to 8bits and much bigger prescaler, so the first round is way off.

void setup() {
  Serial.begin(115200);
  Serial.println("start");
}

#define ENTRIES 5
long stack[ENTRIES+1];
int ctr = 0;

ISR(TIMER1_OVF_vect) {
  TCNT1 = 50000U;
  stack[ctr++] = micros();
  if (ctr &gt; ENTRIES)  TIMSK1 &amp;= ~(1 &lt;&lt; TOIE1);
}

void loop() {
  if (ctr &gt; ENTRIES) {
    for (int i = 0; i &lt; ENTRIES-1; i++) {
      Serial.print(i);
      Serial.print(": ");
      Serial.println(stack[i+1] - stack[i]);
    }
    ctr = 0;
  }

  if (!Serial.available()) return;
  char c = Serial.read();
  if (c == 't') {
    Serial.println("testing");

    stack[0] = micros();
    ctr = 1;

    TCCR1A = 0;           // you have to change the timer mode before changes
    TCCR1B = 0;           // stop the timer
    TIFR1 |= _BV(TOV1);   // clear the overflow interrupt flag by writing 1 to it
    TCNT1  = 50000U;      // tick in around 1ms / this makes more sense if it's set correctly
    TCCR1B = _BV(CS10);   // no prescaler ?????  REALLY???? this one is prescale by 8
    TIMSK1 |= _BV(TOIE1); // enable timer overflow interrupt
  }
}