TOV1 flag on a ATmega32

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

After spending several hours trying to get this VERY simple timer program working I have come to the conclusion I am making a fundamental error.

All I am trying to do is operate the 16bit timer in Normal mode and have it run for a short period of time then stop. I.E. a simple pause, no interrupts.

I can NOT get the TOV1 flag to set, i.e. PORTD just toggles forever, in the code below.

* * * * *
#include
#include "global.h"

int main(void)
{
sbi(DDRD, 7); // set to an output port

// initialize timer1
TCCR1A = 0x00; // normal mode
TCCR1B = 0x03; // timer clocked at F_CPU/64
TCNT1 = 0xFFBA;
TIFR = 0x00;

while((TIFR & TOV1) == 0)
{
PORTD ^= 0x80;
}

while(1)
{;} // hopefully to get a long period of inactivity

return 0;
}

* * * * *

Interrupt driven timers . . . no problem, CTC timer . . . no problem.

Please, what silly mistake am I making.

Thanks,
davef

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

I don't know what compiler and library you are using...
In avr-libc (GCC) TOV1 is a bit number, not a mask. Try

while((TIFR & (1<<TOV1)) == 0)
{
  PORTD ^= 0x80;
}

___(°)^(°)___
A(VR)staroth

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

Thanks for the reply, however that change didn't make any difference. I am using WinAVR and the avr-lib.

It appears to me that TOV1 doesn't get set unless you enable the TOIE1 bit in TIMSK.

Do you need to enable interrupts for Normal mode operation?

Thanks,
davef

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

davef wrote:

Do you need to enable interrupts for Normal mode operation?

It shouldn't...
Enabling TOIE1 but not the global interrupt enable (in SREG) could give you the answer.

___(°)^(°)___
A(VR)staroth

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

If I make both of your recommended changes . . . it WORKS!!!

Thanks for taking the time to see it through to a conclusion.

davef

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

davef wrote:
If I make both of your recommended changes . . . it WORKS!!!

Thanks for taking the time to see it through to a conclusion.

davef


Take care... you're walking on thin ice as you enabled TOIE1 and you probably don't have the related ISR... your program will definitely crash when you'll (global) enable interrupts!

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

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

Thanks Stanley for the added comment. Appears the safest way to do timer related tasks is to ALWAYS use interrupts and write the appropriate ISR to handle it.

Cheers,
davef

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

Oh, it is also possible to do timer things without interrupts (and without the related ISR).
I'm sure there must be something you missed in your program... but now I don't know what.

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

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

I have used timers to several purposes without any interrupts enabled. Please do not make a generalisation that timers are best used with interrupts.

You do have some points where you might shoot yourself in the foot:

The TOV1 flag is set when the timer overflows from 0xffff->0x0000. However, to clear it, you must write a 1 to that bit, not 0. Read the datasheet. And the correct use for the flag reading is, as stated, TIFR & (1<<TOV1).

In tight loops like this, and when using variables, the compiler might optimize the read so, that the variable is only read once to a temporary register and then while is performed to that register, not the variable. However, this should not be the case since this is a hardware register, which the compiler should know. You did not specify what compiler or code optimizing options you use.

Have you tried to simulate/debug your code in AVR Studio? If not, why on earth not?!? You could immediately see that the TIFR register gets TOV1 bit set when the timer overflows, if things are set up correctly. However, sometimes AVR Studio emulates some peripherals wrong, or does not emulate them at all.

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

hi, i'm new studied about uc

can i ask how to read (!(TIFR&(1<<TOV1)))

 

i've studied if (!(PINA & (1<<7))) is PINA.7=0. I think that's PIN.7 is set and then get inverse, so we get PINA.7=0

 

but i can't understand if (!(TIFR&(1<<TOV1))), because it have 2 variabel TIFR and TOV1

 

thx before :)

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

TOV1 is probably bit#2 in the TIFR register.

 

So you are testing whether  TIFR.2 is 0   i.e. the Timer1 Overflow Flag has not occurred yet.

 

Note that you write a 1 to this bit in order to clear it.    e.g. TIFR.2 = 1 (using intuitive parlance for bit operations)

 

Note that the intuitive SFR.# syntax is not standard C.   So you would say TIFR = (1<<2); in GCC

Or preferably:

    TIFR = (1<<TOV1);    //clear the Overflow flag bit

These are difficult concepts.   I suggest that you print the relevant page from your data sheet that describes TOV1.

 

David.

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

david.prentice wrote:

TOV1 is probably bit#2 in the TIFR register.

 

So you are testing whether  TIFR.2 is 0   i.e. the Timer1 Overflow Flag has not occurred yet.

 

Note that you write a 1 to this bit in order to clear it.    e.g. TIFR.2 = 1 (using intuitive parlance for bit operations)

 

Note that the intuitive SFR.# syntax is not standard C.   So you would say TIFR = (1<<2); in GCC

Or preferably:

    TIFR = (1<<TOV1);    //clear the Overflow flag bit

These are difficult concepts.   I suggest that you print the relevant page from your data sheet that describes TOV1.

 

David.

oh, i see. I've forget TOV1 is bit#2 in register TIFR.

 

i study in some books and source, and i get some concept to describe bit in register :)

 

so, (!(PINA & (1<<7))) is bit#7 in register PINA right?

 

thanks, i get the concept :)

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

diazaki wrote:

 

so, (!(PINA & (1<<7))) is bit#7 in register PINA right?

 

thanks, i get the concept :)

 

Hi Diazaki,

 

<< operator is the bit shift, that means, it shifts the bits in a register to the left (and also, >> is bitshift to the right).

in example (1<<7) means that 1 (binary 0000 0001) is shifted 7 times to the left ( 1000 0000 )

then with the & operator you use this mask to clear all the bits of PINA register except that bit, so you can test for this particular bit.

Last Edited: Sun. Jan 31, 2016 - 10:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

karlooie wrote:

diazaki wrote:

 

 

so, (!(PINA & (1<<7))) is bit#7 in register PINA right?

 

thanks, i get the concept :)

 

Hi Diazaki,

 

<< operator is the bit shift, that means, it shifts the bits in a register to the left (and also, >> is bitshift to the right).

in example (1<<7) means that 1 (binary 0000 0001) is shifted 7 times to the left ( 1000 0000 )

then with the & operator you use this mask to clear all the bits of PINA register except that bit, so you can test for this particular bit.

oh, like bitwise operator right?

i've read bitwise operator, understand :)

 

thanks a lot

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

I think you'd benefit greatly from reading this tutorial:

 

https://www.avrfreaks.net/forum/t...

 

It's very important to understand (1 << n), the use of '&', the use of |= and the the use of &= ~(1 << n) as well as the effect '!' has on all that if you are going  to try programming micros - where this occurs all the time.

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

clawson wrote:

I think you'd benefit greatly from reading this tutorial:

 

https://www.avrfreaks.net/forum/t...

 

It's very important to understand (1 << n), the use of '&', the use of |= and the the use of &= ~(1 << n) as well as the effect '!' has on all that if you are going  to try programming micros - where this occurs all the time.

thank for the suggestion :) i've read it in my book. But i need more time to understand all material, because i'm autodidact. I just study with my book, withou teacher :(

 

maybe i need help again for this time :) this is script timer

void delay1detik()
{
    TCCR1B=0b00000101;   
    TCNT1=0xe17b;       
    
    while (!(TIFR&(1<<TOV1)));   
    {
    TIFR=0b00000100;           
    TCCR1B=0b00000000;           
    }    
}

*TCCR1B  for set mode normal, and use prescaler 1024

*TCNT1 for set basic value = 0xe17b

*while (!(TIFR&(1<<TOV1))) is while TOV1 = 0, run 2 script below

*TIFR=0b00000100 for set TOV1 = 1 right?

*TCCR1B=0b00000000 for stop the timer, because theres no clock source

 

I still can't understand description from my book :( point who i got from my book is :

*when TCNT=0 (timer has counting from $00 to $FF), TOV1 =1

 

can anyone help me? :)

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

 

Few observations:

 

1)

 

diazaki wrote:

void delay1detik()
{
    TCCR1B=0b00000101;   
    TCNT1=0xe17b;       
    
    while (!(TIFR&(1<<TOV1)));   
    {
    TIFR=0b00000100;           
    TCCR1B=0b00000000;           
    }    
}

 

 

*while (!(TIFR&(1<<TOV1))) is while TOV1 = 0, run 2 script below

 

notice the final ; on this line:


    while (!(TIFR&(1<<TOV1)));   

the while loop will repeat the check condition until it's not verified, NO script will be executed.

The {} block would be executed only without ; so in this case is meaningless to add these bracket.

 

your script timer will repeat the while line until TOV1 is set, then will execute the remaining two lines to clear TOV1 (to be ready for next call) and stopping the timer (to save power)

 

 

 

 

2)

 

diazaki wrote:

*TIFR=0b00000100 for set TOV1 = 1 right?

 

carefull, you've missed this warning:

Jepael wrote:
However, to clear it [TOV1 flag], you must write a 1 to that bit, not 0. Read the datasheet.
 

this istruction is clearing the flag overflow, not setting it.

 

 

 

3)

 

diazaki wrote:

*when TCNT=0 (timer has counting from $00 to $FF), TOV1 =1

edit: not Notice that in normal mode the timer will always cunt up, and timer 1 has 16 bits. So the overflow happens when counting 0xFFFE .. 0xFFFF .. overflow 0x0000 .. 0x0001

Last Edited: Tue. Feb 2, 2016 - 11:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

karlooie wrote:

 

the while loop will repeat the check condition until it's not verified, NO script will be executed.

The {} block would be executed only without ; so in this case is meaningless to add these bracket.

 

I've understand for thats material :)

 

 

 

However, to clear it [TOV1 flag], you must write a 1 to that bit, not 0. Read the datasheet.

 

 

this istruction is clearing the flag overflow, not setting it.

sorry, maybe i misunderstanding, i think "set" is if we give 1 for a bit. from your argument, i think "set" maybe i can say "active" right? but, active is not must logical 1. example, TOV1 active when 0. not 1

 

this is my comprehension

*start from TCNT=0xe17b will count until max range (currently TOV1 still 0)

*continue to while (!(TIFR&(1<<TOV1))) , because the TOV1 is still 0, script will execute TIFR=0b00000100; for clear it.

*And when timer is reach max range (1second), TOV1 will be 1. And while script will  not execute again

 

I think after TOV1 will be 1, we give TCCR1B=0b00000000 for stop timer. But in other side, when TOV1 will be 1, script will not execute again, so i've try to delete last script (TCCR1B=0b00000000). Timer still work for 1second:)

 

please correct for my comprehension :)

 

thanks