Need help with 8-bit timer

Go To Last Post
30 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define F_CPU 16000000UL

#include <avr/io.h>

void intzar (void)
{
	unsigned char i = 0;
	for (i = 0; i < 100; i++)		//Makes the delay of 1.6384 sec
	{
	TCCR0A = 0xC2;		//CTC mode is used.
	OCR0A = 0xFF;		//8 bit timer
	TCCR0B = 0b00000101;	//prescaler of 1024
	while ((TIFR0 & 0b00000010) == 0b00000010)
	{
		TCCR0B = 0x00;
		TIFR0 = 0x03;
	}
	}
}




int main(void)
{
	DDRB = 0b10000000;
	
	while (1)
	{
		PORTB = 0b10000000;
		intzar();
		PORTB = 0b00000000;
		intzar();
	}
}

Hi guys,

I have written a code to blink an led using an 8 bit timer to produce a delay of 1.6384 sec. As I upload the code to ATmega2560 chip, the led fails to blink. Your guidance would be of great help.

Here is the code. The platform I am using is AtmelStudio7.

This topic has a solution.
Last Edited: Thu. Jul 18, 2019 - 08:36 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Forget the timer based delay for the time being. If you simply use _delay_ms() delays what happens?

 

(IOW is the LED all wired up OK?)

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

I'll add that using binary constants like 0b1000000 is a real invitation to typos (like the one I just made).

 

Use (1 << 7), or

 

#define LED_BIT 7

(1 << LED_BIT)

 

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

A simple delay is working fine.

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

But the code works fine when _delay_ms function is used.

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

Zarrar wrote:

TCCR0B = 0x00;

this code stops the timer, and the for loop can not repeat 100 times secessfully

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

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

Obviously I need to stop the timer as the flag goes high so that the timer gets ready for the next round.

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

Zarrar wrote:

	TCCR0A = 0xC2;		//CTC mode is used.
	OCR0A = 0xFF;		//8 bit timer
	TCCR0B = 0b00000101;	//prescaler of 1024
	while ((TIFR0 & 0b00000010) == 0b00000010)
	{
		TCCR0B = 0x00;
		TIFR0 = 0x03;
	}

Describe what you think this code section does.

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

Zarrar wrote:

Obviously I need to stop the timer as the flag goes high so that the timer gets ready for the next round.

That's almost never how you should use timers (because it introduces timing jitter), but that's not your problem here.

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

Dear I have added comments to the code.

However, in while loop I am monitoring the output compare match flag. As the flag goes high, the timer stops and and the output compare match flag is reset.

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

Suggest the right way.

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

Zarrar wrote:
Suggest the right way.

Not sure its the "right" way but try this:

void intzar (void)
{
	unsigned char i = 0;
	for (i = 0; i < 100; i++)		//Makes the delay of 1.6384 sec
	{
	TCCR0A = 0xC2;		//CTC mode is used.
	OCR0A = 0xFF;		//8 bit timer
	TCCR0B = 0b00000101;	//prescaler of 1024
	while ((TIFR0 & 0b00000010) == 0b00000010);
	
	TCCR0B = 0x00;
	TIFR0 = 0x03;
	
	}
}

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
	while ((TIFR0 & 0b00000010) == 0b00000010)
    {
        ...
    }

You are making the wrong test here.  You are testing for a compare match (OCF0A = 1), and since OCF0A will not be set immediately, your test will fail and your while() loop will exit immediately.

 

And write 0b00000010 as (1 << OCF0A) so your meaning is clear.

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

A relatively new problem now.

This piece of code makes the led glow continuously.

int main(void)
{
	DDRB = 0b10000000;
	
	while (1)
	{
		PORTB = 0b00000000;
		intzar();
		//PORTB = 0b10000000;
		//intzar();
	}
}

While this shuts the led down:

int main(void)
{
	DDRB = 0b10000000;
	
	while (1)
	{
		PORTB = 0b00000000;
		//intzar();
		//PORTB = 0b10000000;
		//intzar();
	}
}

 

Can it be explained...?

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

I also tried the test for timer overflow flag (TOV0 = 1). But it did not solve the problem either.

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

If you haven't fixed your while() problem, there's a good chance that your LED is turning on and off many hundreds or thousands of times per second, far too fast for you to discern.

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

Have fixed the while problem..but the problem persists.

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

Thanks dear.

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

One thing I would like to mention that I am using ATmega2560 on Arduino mega board.

Have done certain changes to program the ATmega2560, on Arduino mega board, through Atmelstudio7.

 

Isn't that causing the issue I am having?

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

Any time you change the code ("fixed a problem") you need to post your entire new code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define F_CPU 16000000UL

#include <avr/io.h>
//#include <util/delay.h>

void intzar (void)
{
	unsigned char i ;
	for (i = 0; i < 100; i++)		//Makes the delay of 1.6384 sec
	{
	TCCR0A = 0xC0;		//NORMAL mode is used.
	OCR0A = 0xFF;		//8 bit timer
 	TCCR0B = 0b00000101;	//prescaler of 1024

	while ((TIFR0 & (1<<TOV0)) == 0b00000001)
	;
		TCCR0B = 0x00;
		TIFR0 = 0x01;

	}
}

int main(void)
{
	DDRB = 0b10000000;

	while (1)
	{
		PORTB = 0b00000000;
		intzar();
		PORTB = 0b10000000;
		intzar();
	}
}

 

Last Edited: Thu. Jul 18, 2019 - 05:38 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you recognize in comment#14 that the calling of intzar(); makes the LED glow continuously...?

I could not understand that.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Please try this.

 

#define F_CPU 16000000UL

#include <avr/io.h>

void intzar (void)
{
    unsigned char i = 0;

    TIFR0 = 0b00000001;     // clear OVF flag
    TCNT0 = 0;              //clear counter
    TCCR0A = 0x00;          //NORMAL mode is used.
    TCCR0B = 0b00000101;    //prescaler of 1024

    for (i = 0; i < 100; i++)       //Makes the delay of 1.6384 sec
    {
        while (!(TIFR0 & 0b00000001));  // wait OVF
        TIFR0 = 0b00000001;             // clear OVF flag
    }
    TCCR0B = 0; // stop TC0
}

int main(void)
{
    DDRB = 0b10000000;
    
    while (1)
    {
        PORTB = 0b10000000;
        intzar();
        PORTB = 0b00000000;
        intzar();
    }
}

 

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

Just to say that it is confusing beyond belief when you write code laid out like this:

	while ((TIFR0 & (1<<TOV0)) == 0b00000001)
	;
		TCCR0B = 0x00;
		TIFR0 = 0x01;

While it is functionality equivalent:

	while ((TIFR0 & (1<<TOV0)) == 0b00000001);
        TCCR0B = 0x00;
	TIFR0 = 0x01;

is far clearer about how these things are related (ie they are not). The curious indentation and "stray semicolon" in the first initially imply something entirely different.

 

PS:

Makes the delay of 1.6384 sec

is the reason you probably want to start reading about "CTC mode" ;-)

(unless you really want a 1.6834 second delay??)

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

Thanks a million dear Kabasan.. :)

 

The code is working fine..

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

Quote:

        while (!(TIFR0 & 0b00000001));  // wait OVF

OP, this is what I was trying to get you to understand,  The correct waiting test is to wait while the flag (overflow or compare) is ZERO, and drop through when it goes to ONE.  Thus it uses the '!' operator in the test.  Your code was waiting while the flag was ONE, and dropped through when it was ZERO, which meant your code never waited because the flag was always ZERO to start with.

Last Edited: Thu. Jul 18, 2019 - 03:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

PS:

Makes the delay of 1.6384 sec

is the reason you probably want to start reading about "CTC mode" ;-)

(unless you really want a 1.6834 second delay??)

I'd suggest to OP that he now figure out how to get 1 ms timer ticks (hint, prescaler of 64, compare value of 250-1).  Then modify intzar to take a delay parameter in milliseconds ( void intzar(uint16_t delay_ms) )

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

Thanks dear kk6gm, your explanation cleared the my realization of the syntax. :)

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

Thank you all for the help.. :)

Last Edited: Thu. Jul 18, 2019 - 04:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Zarrar wrote:

while (some_flag == 1)
    {
        ...
    }

kk6gm, I couldn't understand that when I am masking the TIFR0 register (with 0b00000001) and waiting for that timer overflow flag to be ONE; how the test is going wrong..?

 

 

Here is the sequence you were using:

 

some_flag = 0;    // flag starts out NOT set

 

while (flag == 1)  // since flag is ZERO, this while() immediately drops through

  ;

 

// we get here immediately, which is wrong!

 

-----------------

 

Here is the sequence you want:

 

some_flag = 0;

 

while (some_flag == 0)  // now it waits for some_flag to get set to ONE

  ;

---OR---

while (!some_flag)   // note use of '!' operator

  ;

 

// we only get here when some_flag changes from ZERO to ONE

 

-----------------

 

Now for some other ways to make your code cleaner:

 

while (!(TIFR0 & (1<<TOV0)))
  ;

First note the use of the bit identifier TOV0 rather than a magic number like 0b00000001.  Other compilers might supply a bit mask so you might write !(TIFR0 & TOV0_MASK)

 

Second, note that there is no reason to explicitly compare a single bit to zero or non-zero using ==.  The expression !(TIFR0 & (1<<TOV0)) already returns a value of zero or non-zero, which can be tested directly, without using ==

Last Edited: Thu. Jul 18, 2019 - 05:17 PM