ATmega324 Asynchronous timer wakeup

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

Hi

For some reason this code doesn't work properly & i have tried everything i know & read the data sheet. It is supposed to send the micro to sleep then wake two seconds later & toggle the led. Its weird but if i do a fuse read it starts working, i don't know why.

#include 
#include 
#include 
#define F_CPU 7372800


ISR ( TIMER2_COMPA_vect )
{
	PORTD ^= (1 << 7); // Toggle the LED
}

int main (void)
{
	DDRD = 0b10000000;             //Make OC2A an output so the clock can be seen
	//Setup for timer
	ASSR |= (1<<AS2);              //Timer/Counter2 is clocked from a crystal Oscillator connected to the Timer Oscillator1 (TOSC1) pin.
	TCCR2A |= (1<<WGM21);          //CTC mode
	TCCR2B |= (1<<CS21)|(1<<CS22); //Prescaler 256
	OCR2A = 255;                   //255 should be equal to 2seconds at prescaler of 256 32.768Khz external crystal.
	while ((ASSR & (1<<TCN2UB)&(1<<OCR2AUB)&(1<<OCR2BUB)&(1<<TCR2AUB)&(1<<TCR2BUB)) == 1);
	TIMSK2 |= (1<<OCIE2A); //Timer/Counter2 Compare Match A interrupt is enabled.
	//Setup for sleep mode.
	PRR |=(1<<PRTWI);
	set_sleep_mode(SLEEP_MODE_EXT_STANDBY);
        sleep_bod_disable();
	sleep_enable();
	sei();
	
	for(;;)
	{
	sleep_cpu();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are only going to sleep once.

What exactly is happening?

I might try something repetitive, and/or have some "secondary" LEDs to tell what state you are in. with your "once only", you could e.g. be seeing an initial false trip.

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

It just goes to sleep & doesn't wake up. Sometimes it might work & then others it wont.
Update:
Its like the timer doesn't get setup properly because if i add a one second delay as in this code it runs flawlessly. I randomly picked the one second delay.
Any ideas?

#include 
#include 
#include 
#define F_CPU 7372800
#include 

ISR ( TIMER2_COMPA_vect )
{
   PORTD ^= (1 << 7); // Toggle the LED
}

int main (void)
{
   DDRD = 0b10000000;             //Make OC2A an output so the clock can be seen
   //Setup for timer
   ASSR |= (1<<AS2);              //Timer/Counter2 is clocked from a crystal Oscillator connected to the Timer Oscillator1 (TOSC1) pin.
   TCCR2A |= (1<<WGM21);          //CTC mode
   TCCR2B |= (1<<CS21)|(1<<CS22); //Prescaler 256
   OCR2A = 255;                   //255 should be equal to 2seconds at prescaler of 256 32.768Khz external crystal.
   while ((ASSR & (1<<TCN2UB)&(1<<OCR2AUB)&(1<<OCR2BUB)&(1<<TCR2AUB)&(1<<TCR2BUB)) == 1);
   TIMSK2 |= (1<<OCIE2A); //Timer/Counter2 Compare Match A interrupt is enabled.
   _delay_ms(1000); //Added delay & it works
   //Setup for sleep mode.
   PRR |=(1<<PRTWI);
   set_sleep_mode(SLEEP_MODE_EXT_STANDBY);
        sleep_bod_disable();
   sleep_enable();
   sei();
   
   for(;;)
   {
   sleep_cpu();
   }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
while ((ASSR & (1<<TCN2UB)&(1<<OCR2AUB)&(1<<OCR2BUB)&(1<<TCR2AUB)&(1<<TCR2BUB)) == 1);
Wrong in two ways. Left side of == is always 0, and the "== 1" is wrong too.

Stefan Ernst

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

Quote:

while ((ASSR & (1<<TCN2UB)&(1<<OCR2AUB)&(1<<OCR2BUB)&(1<<TCR2AUB)&(1<<TCR2BUB)) == 1);
Wrong in two ways. Left side of == is always 0, and the "== 1" is wrong too.

Ok so what is correct way then?

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

warren1 wrote:
Ok so what is correct way then?
Try harder yourself first. That is basic bit arithmetic. You really need to learn such basics.

[TUT] [C] Bit manipulation (AKA "Programming 101")

Stefan Ernst

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

Even reading that example im not 100% sure what you are saying. Anyway do you know what could be causing the problem above?

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

Tell you what - why don't you try explaining what the line:

   while ((ASSR & (1<<TCN2UB)&(1<<OCR2AUB)&(1<<OCR2BUB)&(1<<TCR2AUB)&(1<<TCR2BUB)) == 1); 

is doing? Bear in mind that a header file somewhere says:

#define TCN2UB 4
#define OCR2AUB 3
#define OCR2BUB 2
#define TCR2AUB 1
#define TCR2BUB 0

So the line says:

   while ((ASSR & (1<<4)&(1<<3)&(1<<2)&(1<<1)&(1<<0)) == 1); 

which is:

   while ((ASSR & 0x10 & 0x08 & 0x04 & 0x02 & 0x01) == 1); 

Forget the ASSR in this what does

0x10 & 0x08 & 0x04 & 0x02 & 0x01

equate to?

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

warren1 wrote:
Even reading that example im not 100% sure what you are saying. Anyway do you know what could be causing the problem above?
The loop does not do what it should do, to wait until all the named bits become 0.

   _delay_ms(1000); //Added delay & it works 

Because now the delay does the waiting.

Stefan Ernst

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

Thanks for that sternst it confirmed what i was thinking, why didn't you say that at the start :)

Its kind of tricky if i leave out the ASSR as that is what i consider to be the byte & the 0x10 etc to be the bits. As in that [TUT] [C] Bit manipulation (AKA "Programming 101").

Ok so if i use clawson's code of

0x10 & 0x08 & 0x04 & 0x02 & 0x01

Considering anything over 1 is 1 & making it to a binary format of

1 & 1 & 1 & 1 & 1

using a truth table for AND would mean that this = 1
However that could be a problem. Because if i look at the rest of the AND truth table & if there was a 0 in the string of 1's the answer would be 0.
Therefore my code would exit which would not be good as some of the timer bits might still be set.

However if i use the OR it should work. But it didn't. I got a warning saying i needed extra brackets. I put in brackets & removed part of the timer i didn't use. Still no luck.

while ((ASSR & ((1<<TCN2UB)|(1<<OCR2AUB)|(1<<TCR2AUB))) == 1);
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Considering anything over 1 is 1

??? Why would you say that?!? Flat out wrong. You are using (and >>should<< be using) the bit-wise operators and not the logical (&&) operators.

You need some (much?) practice on bit manipulations and logical operators.

short answer to get you going:

   while ((ASSR & ((1<<TCN2UB)|(1<<OCR2AUB)|(1<<OCR2BUB)|(1<<TCR2AUB)|(1<<TCR2BUB))) == 1); 

constructs a bit mask of the 5 bits at compile time, and then the loop will continue while ASSR and'ed with that bit mask has the value exactly 0x01. Now, is this really the way you wait? It doesn't sound right to me.

Lee

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, your confusing me more but i know im incredibly slow. If you are saying

Quote:

while ((ASSR & ((1<<TCN2UB)|(1<<OCR2AUB)|(1<<OCR2BUB)|(1<<TCR2AUB)|(1<<TCR2BUB))) == 1);

Should work, it doesn't as i tired it.

What i expect the above code to do is check each flag/bit TCN2UB, OCR2AUB etc if they are a 1 or a 0 in the ASSR register. If any of them is a 1 then don't exit as the timer is not set yet.

1 = Not ready
0 = Ready

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

Quote:

If any of them is a 1

No, that is NOT the way that C statement is written.
Quote:

What i expect the above code to do is check each bit TCN2UB, OCR2AUB etc if they are a 1 or a 0 in the ASSR register. If any of them is a 1 then don't exit as the timer is not set yet.

A fairly straightforward way would be

while ((ASSR & ((1<<TCN2UB)|(1<<OCR2AUB)|(1<<OCR2BUB)|(1<<TCR2AUB)|(1<<TCR2BUB))) != 0); 

But as I read the datasheet most of those bits are unrelated to your task at hand.

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

Ahh really. Crap! i could have sworn i was reading the code right. :)

May i ask another stupid question & say. Is it bad/illegal to use a 1 in a while statement?
If so that may explain what i expect it to do vs what the compiler does with it.

I did remove OCR2BUB & TCR2BUB as im not using the B timer. I did that in a above post so your right theusch.

This code works

while ((ASSR & ((1<<TCN2UB)|(1<<OCR2AUB)|(1<<TCR2AUB))) != 0);
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
May i ask another stupid question & say. Is it bad/illegal to use a 1 in a while statement?
If so that may explain what i expect it to do vs what the compiler does with it.
warren1,
it is quite obvious that you have still big problems with the basic binary arithmetic. You REALLY need to learn that first.
What is the result of "0x0f & 0x04"? (No, it is not 1)

Stefan Ernst

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

I have only ever been able to learn by example. If there is a change to the example then i don't know what to do.
e.g algebra was a lost cause to me, it seemed to be all guess work & i never saw a structure. That was a long time ago now, i maybe able to work it out.

Your example would require guess work. Looking at the truth table there isn't an example for the big numbers you have stated. However if i convert the two numbers to binary & put them over & under each other like this

1111 (0x0F)
0100 (0x04)

i could pair them out.

1 1 1 1
0 1 0 0

Puting each of those pairs through the truth table would end up with 0100 (0x04)

Truth table for AND
0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1

This still may not be correct.
How this would apply to the While statement if that's what you are talking about would need to be explained in steps also lol.

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

Quote:
Puting each of those pairs through the truth table
Which is exactly what "bitwise" means in "bitwise and (&)", "bitwise or (|)", etc.
Quote:
would end up with 0100 (0x04)
Correct.

Quote:
How this would apply to the While statement if that's what you are talking about would need to be explained in steps also lol.
Let's simplify your while a little:
while ((REG & (1<<BIT)) == 1); 

Now let's assume BIT is 2, what is now the result of the left side if that bit is 1 in REG?

Stefan Ernst

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

Quote:

Now let's assume BIT is 2, what is now the result of the left side if that bit is 1 in REG?

Ok so "result of the left side" means "Answer"

Answer = while ((1 & (1<<2)) == 1);
Answer = while ((1 & (1<<0b0000010)) == 1);
due to the bit shift left (1<<0b0000010) = 1
Answer = while ((1 & (1)) == 1);

binary convert
01 (1)(From shift left one)
01 (1)(REG)

01

Answer = while ((1)) == 1);
Answer = True continue loop

If this is the case why specify (1<<x)?
Wouldn't the (1<<x) end up pointing to the wrong bit.

e.g AS2 == (1<<TCN2UB)
or 1 == (1<<2)

Should it be just (TCN2UB) for checking the flag purpose?

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

Can you actually confirm you have read the bit manipulation 101 thread? What parts of it did you not understand?

Answer = while ((1 & (1<<2)) == 1);
Answer = while ((1 & (1<<0b0000010)) == 1);

Wrong already 1<<2 is 0b00000100 not 0b00000010

due to the bit shift left (1<<0b0000010) = 1

No that is equal to FOUR not ONE?! So the following becomes

Answer = while ((1 & (4)) == 1); 

In this "1 & 4" is equal to 0. It's easier to see if you stick to binary and write them down one above the other:

0b00000001
0b00000100
==========

Take each digit position in turn and perform the & operation on the 1's and 0's you see. In the right most bit position 0 the top line is 1 and the bottom is 0, 1 AND 0 is 0 so that resultant bit (that you write under the === line) is 0. Now move left one place to bit position 1. That is 0 AND 0. The result there is 0. Now move to bit position 2. 0 AND 1 is 0 and for the next five bit positions it is all 0 AND 0. So you get the result:

0b00000001
0b00000100
==========
0b00000000

You said above you cannot do algebra. That is a bit of a shame. What we are doing here is called boolean algebra an it's absolutely fundamental to programming computers. If you cannot grasp the concepts then you are not going to make it as a programmer.

Consider now what happens when the item on the left actually does have bit 2 set. So now you have:

Answer = while ((0b00000100 & (1<<0b0000100)) == 1);

So once again do the AND operation a bit at a time and you get:

0b00000100
0b00000100
==========
0b00000100

Finally a non-zero result. In bit position 2 both sides held a 1 and 1 AND 1 is 1. But the overall result here is 0b00000100 which is FOUR not ONE. So if you test the whole thing for equality to 1 (== 1) that will never be true. What is tue (that wasn't before) is that our result is non-zero and rather handily C treats anything non-0 as true so we can test if bit 4 is set with something like:

while (ASSR & (1<<2)) {
  // something
}

That "// something" will continue to be done as long as bit 2 in ASSR is set.