how to reset a timer manually?

I'm using TIMER5_COMPC_vect. CTC is disabled because i want to reset the timer manualy. in the ISR i use sei() to enable global interrupts (TIMER5_COMPC_vect doing some long task, lets say 100 ms, and i want to enable other interrupts durring this time).

lets say this is my code inside the ISR:

ISR(TIMER5_COMPC_vect)
{
TIMSK5 &= ~(1<<OCIE5A); //block the timer
 sei();//set interrupt

//do somthing that takes 100 ms

TCNT5=0;//reset timer
TIMSK5 |= (1<<OCIE5A);//enable the timer
}

the reson for manual reset is because i want the ISR to jump again 20 ms after it finished, but for some reason it dosn't work for me.
i set the compare register to 40000 (with prescalling of 8) but it seems thet this ISR jumps again immediately after it finished.
what i'm doing wrong here?

First, doing something lengthy in an interrupt, and turning interrupts back on, isn't a great idea.

Next, you haven't stopped the timer, you just stopped interrupts. The timer is still running, generating interrupt events. Then when you re-enable interrupts it would immediately fire.

Try (if you must do it this way) resetting the interrupt mask (see TIFR5).

The comment is wrong:

TIMSK5 |= (1<<OCIE5A);//enable the timer

Should read:

TIMSK5 |= (1<<OCIE5A);//enable interrupts on Output Compare A Match

thanks.

i can't understand how this flags work.

the manual says:

OCFnC is automatically cleared when the Output Compare Match C Interrupt Vector is executed. Alternatively,
OCFnC can be cleared by writing a logic one to its bit location.

so i need to put 1 in the register to clear the interrupt? isn't it supposed to be 0?

Yes, it is cleared when you enter the ISR. But you enable interrupts, the timer is still running, the timer matches again while you are mucking around for 100 mS and the flag gets set again. Then you enable the interrupts and it immediately fires. Here is proof:

volatile bool fired;
volatile unsigned long whenFired;
volatile byte savedTIFR1;

unsigned long start;

ISR (TIMER1_COMPA_vect)
  {
  savedTIFR1 = TIFR1;
  whenFired = micros ();
  fired = true;
  TCCR1B = 0;  // stop timer
  }  // end of TIMER1_OVF_vect


void setup ()
  {
  Serial.begin (115200);
  Serial.println ();

  // Timer 1 - counts events on pin D5
  TIMSK1 = bit (OCIE1A);   // interrupt on Timer 1 Compare A match
  TCNT1 = 0; 
  TCCR1A = 0;
  TIFR1 = 0xFF;  // reset flags
  start = micros ();
  TCCR1B =  bit (WGM12) | bit (CS11) ;  // CTC prescaler 8
  OCR1A = 49999;  //  count to 50000
  OCR1B = 60000; 
  }  // end of setup

void loop ()
  {
  if (!fired)
     return;
    
  Serial.print ("Fired! Took ");
  Serial.println (whenFired - start); 
  Serial.print ("TIFR1 = ");
  Serial.println (savedTIFR1, HEX); 
   
  
  fired = false;
  }  // end of loop

Output:

Fired! Took 25008
TIFR1 = 0

So the flag is cleared entering the interrupt.


Now let's build a delay into the interrupt, like you did:

volatile bool fired;
volatile unsigned long whenFired;
volatile byte savedTIFR1;
volatile int counter;

unsigned long start;

ISR (TIMER1_COMPA_vect)
  {
  counter++;
  
  savedTIFR1 = TIFR1;
  whenFired = micros ();
  fired = true;
  TIMSK1 &= ~(bit (OCIE1A));   // no interrupt on Timer 1 Compare A match

  if (counter > 2)
    return;

  sei ();
  // wait half a second
  for (int i = 0; i < 50; i++)
    delayMicroseconds (10000);  
    
  start = micros ();
  TCNT1 = 0; 
  TIMSK1 = bit (OCIE1A);   // interrupt on Timer 1 Compare A match
  }  // end of TIMER1_OVF_vect


void setup ()
  {
  Serial.begin (115200);
  Serial.println ();

  noInterrupts ();
  
  // Timer 1 - counts events on pin D5
  TIMSK1 = bit (OCIE1A);   // interrupt on Timer 1 Compare A match
  TCNT1 = 0; 
  TCCR1A = 0;
  TIFR1 = 0xFF;  // reset flags
  start = micros ();
  TCCR1B =  bit (WGM12) | bit (CS11) ;  // CTC prescaler 8
  OCR1A = 49999;  //  count to 50000
  OCR1B = 60000; 
  interrupts ();
  }  // end of setup

void loop ()
  {
  if (!fired)
     return;
    
  Serial.print ("Fired! Took ");
  Serial.println (whenFired - start); 
  Serial.print ("TIFR1 = ");
  Serial.println (savedTIFR1, HEX); 
  fired = false;
  }  // end of loop

Output:

Fired! Took 8
TIFR1 = 0

8 µS? It was supposed to be 25008! The timer must have fired immediately!

volatile bool fired;
volatile unsigned long whenFired;
volatile byte savedTIFR1;
volatile int counter;

unsigned long start;

ISR (TIMER1_COMPA_vect)
  {
  counter++;
  
  savedTIFR1 = TIFR1;
  whenFired = micros ();
  fired = true;
  TIMSK1 &= ~(bit (OCIE1A));   // no interrupt on Timer 1 Compare A match

  if (counter > 2)
    return;

  sei ();
  // wait half a second
  for (int i = 0; i < 50; i++)
    delayMicroseconds (10000);  
    
  TCNT1 = 0; 
  TIFR1 |= bit (OCF1A);  // clear Output Compare A Match Flag
  start = micros ();
  TIMSK1 = bit (OCIE1A);   // interrupt on Timer 1 Compare A match
  }  // end of TIMER1_OVF_vect


void setup ()
  {
  Serial.begin (115200);
  Serial.println ();

  noInterrupts ();
  
  // Timer 1 - counts events on pin D5
  TIMSK1 = bit (OCIE1A);   // interrupt on Timer 1 Compare A match
  TCNT1 = 0; 
  TCCR1A = 0;
  TIFR1 = 0xFF;  // reset flags
  start = micros ();
  TCCR1B =  bit (WGM12) | bit (CS11) ;  // CTC prescaler 8
  OCR1A = 49999;  //  count to 50000
  OCR1B = 60000; 
  interrupts ();
  }  // end of setup

void loop ()
  {
  if (!fired)
     return;
    
  Serial.print ("Fired! Took ");
  Serial.println (whenFired - start); 
  Serial.print ("TIFR1 = ");
  Serial.println (savedTIFR1, HEX); 
  fired = false;
  }  // end of loop

Output:

Fired! Took 4294464280
TIFR1 = 0
Fired! Took 4294464280
TIFR1 = 0
Fired! Took 25004
TIFR1 = 0

4294464280?

You will spend all day getting rid of race conditions in your ISR if you insist on enabling interrupts. I recommend you don't.