Timer Interrupt question

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi everyone!

What happens if I set the Timer Interrupt Enable flag after the timer overflow flag has been set? Will the interrupt routine fire that time, or only next time an overflow occurs?

Scenario is this:

I have to call a function every 50us, so I made timer interrupt routine call it from time to time.

while(1)
{
// Do something non-critical here
TIMSK &= ~ (1<<TOIE0);
// Do something critical here
if (messages pending)
{
handle 1 message;
remove message from queue;
}
TIMSK |= (1<<TOIE0);
}

If I get one message at a time, it works flawlessly. If I send more messages at once, communication stops because the function didn't get called for some reason. The critical part never grows in length, but is called more often during load.
Even if the timer overflow occurs during the critical part, the interrupt routine should be called after reaching the TIMSK |= (1<<TOIE0) instruction, shouldn't it? My guess is that is doesn't get called, and that's why my program doesn't work.

Regards,

axos88

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Its hard to say with the little information you provided. How about showing your timer0 setup program code. Telling us which AVR you're using, what your AVR clock frequency is and which C compiler you are using.

Since its supposed to fire every 50 microseconds, how much of that time is consumed by your timer0 overflow interrupt service program code?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi!

Sorry for my vagueness!
I am using the mega8515 (i know it is kinda old, but the only chip with an external mem interface for a reasonable price), with a 12Mhz clock.
I am using the GCC C ompiler.
(And it should fire every 50ms, not us, that was a typo, sorry!)

This is the initialization section of the timer:

//Enable timer0 for usb_poll()
TCCR0 = 0b00000011;
TIMSK |= (1<<TOIE0);
TIMSK &= ~ (1<<OCIE0);

My timer interrupt routing shouldn't be that long (maximum 1-2ms), and is not dependant on the current load.

Regards,

axos88

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Will the interrupt routine fire that time

Yes. If the interrupt flag is set when that interrupt is enabled, then the interrupt will be handled immediately (or more specifically, after one more opcode is run).

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your timer0 setup is: Normal Mode TOP = 0xFF, OC0 disconnected, prescaler divide by 64

Normal mode simply counts from 0 to 255 (0xFF) then starts over at zero (this is 256 total counts). The TOV0 overflow interrupt flag will set each time the count starts over at zero (the overflow event). See the data sheet page 85 Normal Mode. Responding to the overflow interrupt ISR will automatically clear the TOV0 interrupt flag and TOV0 will be set again on the next timer0 overflow.

12 MHz CLKio / prescaler 64 = 187.5 Khz and 187.5 Khz count frequency / 256 timer0 counts = 732.42 Hz which is 1.36533 milliseconds

Simplified this is: time = ((prescaler * 256 TOP) / AVR CLKio)

Solved for prescaler is: prescaler = ((AVR CLKio * time) / 256 TOP), which is a 2343.75 prescaler with your AVR clock frequency and timer0 mode for a 50 ms time.

There isn't any timer0 prescaler for 2343.75. The highest prescaler is divide by 1024. So, ((1024 * 256 TOP) / AVR CLKio) = 21.84533 milliseconds

I just woke up, so I hope I got the figures right :). With your AVR clock frequency the 8 bit timer0 doesn't have the resolution to make 50 milliseconds. Even using Phase Correct PWM which counts up then down, which doubles the overflow time, would only get you to 43.69 milliseconds. You will have to use the 16 bit timer1 for 50 ms at this AVR clock speed, or the external timer0 clock (the T0 pin) with a slower clock source.

For the timer0 overflow interrupt use: ISR (TIMER0_OVF_vect )
http://www.nongnu.org/avr-libc/u...

and don't forget the: sei();

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The usual way to prevent an interrupt inside a critical piece of code is to use cli()... sei().

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The usual way to prevent an interrupt inside a critical piece of code is to use cli()... sei().

Yes, but this prevents all interrupts from happening. If you want to just prevent a single interrupt, then you can disable just that interrupt.

Regards,
Steve A.

The Board helps those that help themselves.