Proper use of the TOV1 flag

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

As I wanted a long time period I thought I would just use the TOV1 flag.  Couldn't get it to work so searched this site and the first hit was mine, 10 years ago and with no useful outcome.

So, after reading Chapter 7 in Deans's timer tutorial I tried using the following code:
 

# include <avr /io.h>
int main ( void )
{
   DDRB |= (1 << 0); // Set LED as output
   TCCR1B |= (1 << WGM12 ); // Configure timer 1 for CTC mode
   OCR1A = 15624; // Set CTC compare value to 1Hz at 1 MHz AVR clock , with a prescaler of 64
   TCCR1B |= ((1 << CS10 ) | (1 << CS11 )); // Start timer at Fcpu /64
   
   for (;;)
   {
      if ( TIFR & (1 << OCF1A ))
      {
         PORTB ^= (1 << 0); // Toggle the LED
         TIFR = (1 << OCF1A ); // clear the CTC flag ( writing a logic one to the set flag
         clears it)
      }
   }
}

 

Worked great using the OCR1A flag.  I thought if I just want a timer overflow why not just look for the TOV1 flag, like this:
 

 

# include <avr /io.h>
int main ( void )
{
   DDRB |= (1 << 0); // Set LED as output
   TCCR1B |= (1 << WGM12 ); // Configure timer 1 for CTC mode
   TCCR1B |= ((1 << CS10 ) | (1 << CS11 )); // Start timer at Fcpu /64
   
   for (;;)
   {
      if ( TIFR & (1 << TOV1 ))
      {
         PORTB ^= (1 << 0); // Toggle the LED
         TIFR = (1 << TOV1 ); // clear the flag
      }
   }
}

Doesn't work.  Only by trying various things did I manage to get it to "work" by adding the line:
OCR1A = 65535; // before the for(;;) loop

 

The only mention I could find is:

 

15.2.2 where the TOP value is defined

 

The counter reaches the TOP when it becomes equal to the highest value in the count
sequence. The TOP value can be assigned to be one of the fixed values: 0x00FF, 0x01FF,
or 0x03FF, or to the value stored in the OCR1A or ICR1 Register. The assignment is
dependent of the mode of operation.

 

Am I using TOV1 flag correctly?   Note: it would only work with OCR1A = 65535

It seems odd to me that if the TOV1 flag only works at 65535 then why do you need to set OCR1A to 65535?

 

 

Last Edited: Mon. Aug 17, 2015 - 08:30 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But you are starting the timer in CTC mode? If you want to use overflows try starting it in normal mode.

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

Haven't checked (sorry I'm a little lazy) but I think if you are using CTC mode where either ICR1 or OCR1A with a top value < 0xFFFF, then technically the timer does not overflow (from 0xFFFF to 0x0000) and so the TOVIF will not be set.  I may be wrong and the TOFIF flag gets set whenever the timer hits 0 but I think this is for the xmega timers.

 

Steve
 

 

<edit> aw pipped by 6 mins

Last Edited: Mon. Aug 17, 2015 - 08:38 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the clues guys.  Operating it in normal mode results in expected behaviour.

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

Operating it in normal mode results in expected behaviour.

Now, which AVR model are you working with?  And you discussed all around it, but tell more about "expected".

 

A typical timer1 mode chart (extract):

For CTC modes, "TOV1 Flag Set on MAX".  With your problem code, does TCNT1 ever reach MAX?  No.  Thus, your original symptoms are "expected".

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch,

 

ATmega88.  Before post #4 I had done a search on MAX and didn't see any clue as to what it meant.   I'll make a guess that MAX actually means 0x0000 as per post #3.  Am I getting closer?

 

The fact that it "worked" correctly with OCR1A = 65535 was just an "unfortunate circumstance"?

 

Expected means I get a timer overflow, which triggers a watchdog reset.  Rather than toggle a LED, as per Dean's example.

 

 

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

I had done a search on MAX and didn't see any clue as to what it meant.

Does your copy of the datasheet not contain this then? Ctrl-F will usually find text such as "MAX" in PDFs ;-)

 

Last Edited: Tue. Aug 18, 2015 - 08:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I had found many hits on MAX in the datasheet, I think what I am trying to convey is that I still didn't understand some of the perceived differences in the information as presented.

 

As you point out ... the counter reaches MAX when it becomes 0xFFFF, but then what happens?  According to table Table 15-4  the TOV1 flag is set when the counter reaches MAX.

 

But then in 15.9.1

In normal operation the Timer/Counter Overflow Flag (TOV1) will be set in
the same timer clock cycle as the TCNT1 becomes zero.

Then I got totally confused when I appeared to force the TOV1 flag to be set when I put the statement OCR1A = 65535; ie MAX as in the original post. 

 

I believe I have a better understanding of where I made the some wrong assumptions, but at the end of the day I have some code that appears to work in a "more expected way".

 

Thanks.

 

 

 

Last Edited: Tue. Aug 18, 2015 - 09:26 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Doesn't work.  Only by trying various things did I manage to get it to "work" by adding the line:
OCR1A = 65535; // before the for(;;) loop

Just think about this for a moment. What actually happens in CTC mode? The timer starts at 0. It counts up until it matches OCR1A and then it resets and starts over. Meanwhile the datasheet tells us that MAX=65535 (0xFFFF) and also that TOV is set at MAX. So if you don't actually write a value to OCR1A then what value will it hold? Again the datasheet tells us it defaults to 0x0000.

 

So when you switched the code from compare to overflow you were still in CTC, but because you hadn't set it OCR1A was 0x0000 so the timer would count 0, 0, 0, 0, 0... setting the compare flag each time it hit 0 (and then resetting). There was never any possibility of it counting 0,1,2,3.. 65534, 65535. But then you  said:

Only by trying various things did I manage to get it to "work" by adding the line:
OCR1A = 65535; // before the for(;;) loop

Well yes, that does not allow the timer to count all the way from 0,1,2,3,4... to 65535 and because 65535 is MAX this also then meant that it got to set TOV.

 

The chip is doing exactly what the datasheet says it would do.

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

The very first hit on MAX with my PDF search, case-sensitive and whole-words, is the definition for Timer0.

 

There is no conflict with your quote

But then in 15.9.1

In normal operation the Timer/Counter Overflow Flag (TOV1) will be set in
the same timer clock cycle as the TCNT1 becomes zero.

That just means that the flag is actually set when ready for the next timer tick.  (which may be many AVR clock cycles if a prescaler is used.

 

Also, you cherry-picked that quote a bit.  For one, it is from the chapter on 8-bit timer?  Perhaps not; I may be using a different datasheet.  Below are the start of the paragraphs for Normal Mode for timer0 and timer1:

 

15.7.1 Normal Mode
The simplest mode of operation is the Normal mode (WGM02:0 = 0). In this mode the counting direction is
always up (incrementing), and no counter clear is performed. The counter simply overruns when it passes its
maximum 8-bit value (TOP = 0xFF) and then restarts from the bottom (0x00). In normal operation the
Timer/Counter Overflow Flag (TOV0) will be set in the same timer clock cycle as the TCNT0 becomes zero.

 

16.9.1 Normal Mode
The simplest mode of operation is the Normal mode (WGM13:0 = 0). In this mode the counting direction is
always up (incrementing), and no counter clear is performed. The counter simply overruns when it passes its
maximum 16-bit value (MAX = 0xFFFF) and then restarts from the BOTTOM (0x0000). In normal operation the
Timer/Counter Overflow Flag (TOV1) will be set in the same timer clock cycle as the TCNT1 becomes zero.

 

Lessee if there is a different description in CTC mode section:

As for the Normal mode of operation, the TOV1 Flag is set in the same timer clock cycle that the counter counts
from MAX to 0x0000.

 

 ...which is what you found when you set OCR1A to 0xffff.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.