You have to wait for the characyter to lkeave the uart --- then goto sleep.
I use ATMEGA128 with UART and also with external 32KHz xtal on
timer 0 for power save modes. So far I'm down to 35uA. Be careful
with external pull-ups, make sure ports are configured for input lest the
chew up power while in sleep. Shut everything else off --- including
JTAG debug interface, analog comparator, and watchdog timer
(can be done in software), otherwise you will not get anywhere near
10's of uA.
David Howard
"Ken Scharf" <wa2mzeNOTTHIS@bellsouth.net> wrote in message
news:oRY3f.18754$Yl.4065@bignews4.bellsouth.net...
> Meindert Sprang wrote:
> > <ilovecpp@gmail.com> wrote in message
> > news:1121844978.458057.302820@g43g2000cwa.googlegroups.com...
> >
> >>Thank you Meindert Sprang.
> >>
> >>But It's a little bit different. In my case, I fix code like below.
> >>
> >>void main(void)
> >>{
> >> Hardware_Init();
> >>
> >> while(1)
> >> {
> >> Uart_Put_Char('A');
> >> __asm volatile ("sleep");
> >> Uart_Put_Char('B');
> >> }
> >>}
> >>
> >>and My system doesn't print even "A".
> >
> >
> > That is most likely because you put the AVR to sleep before the "A" has
left
> > the UART. Your Uart_Put_Char() first checks the UDRE bit, then it loads
a
> > new byte in the UDR register. If you then call "sleep", the AVR goes to
> > sleep before the UART has finished shifting the byte out. Checking for
UDRE
> > *after* the write to UDR doesn't help either because the UART is double
> > buffered. UDRE flags the state of the UDR register and not the shift
> > register. To test this, insert
> >
> > while ( !( UCSRA & (1<<TXC)) );
> >
> > before the "sleep" instruction. This will test if the shifter is really
> > empty and thus you have seen the "A" appear.
> >
> > Meindert
> >
> >
> >
> If his uart transmit routine were interrupt driven then the avr
> might go to sleep and wake up in the transmit routine. Note that
> there are different sleep modes you can specify, and some of them
> will NOT allow the uart to run, there is a mode that WILL allow the
> uart to receive data while the cpu is asleep and you need to use
> that mode to wake up on a character received. Of course the power
> savings isn't as great with this mode.....
>
> BTW, I'm working on a project with a mega128 avr using external
> ram. In putting this one to sleep I first disabled external memory
> mode so the chip select of the ram (wired to A15) would go high to
> save the current pulled by the selected ram chip (dropped about
> 30ma!). But to do this I first had to relocate the stack to internal
> ram (I'll leave the reason for this as an excerise for the reader!).
> The stack is restored after the cpu wakes up. The cpu is put to sleep
> in mainline code, ANY interrupt will wake up the cpu, and after
> returning from interrupt we are at the instruction AFTER the sleep
> instruction. NOTE that the interrupt code must NOT access any data
> in external ram! (think of all the fun I am having with this!)
Reply by Ken Scharf●October 14, 20052005-10-14
Meindert Sprang wrote:
> <ilovecpp@gmail.com> wrote in message
> news:1121844978.458057.302820@g43g2000cwa.googlegroups.com...
>
>>Thank you Meindert Sprang.
>>
>>But It's a little bit different. In my case, I fix code like below.
>>
>>void main(void)
>>{
>> Hardware_Init();
>>
>> while(1)
>> {
>> Uart_Put_Char('A');
>> __asm volatile ("sleep");
>> Uart_Put_Char('B');
>> }
>>}
>>
>>and My system doesn't print even "A".
>
>
> That is most likely because you put the AVR to sleep before the "A" has left
> the UART. Your Uart_Put_Char() first checks the UDRE bit, then it loads a
> new byte in the UDR register. If you then call "sleep", the AVR goes to
> sleep before the UART has finished shifting the byte out. Checking for UDRE
> *after* the write to UDR doesn't help either because the UART is double
> buffered. UDRE flags the state of the UDR register and not the shift
> register. To test this, insert
>
> while ( !( UCSRA & (1<<TXC)) );
>
> before the "sleep" instruction. This will test if the shifter is really
> empty and thus you have seen the "A" appear.
>
> Meindert
>
>
>
If his uart transmit routine were interrupt driven then the avr
might go to sleep and wake up in the transmit routine. Note that
there are different sleep modes you can specify, and some of them
will NOT allow the uart to run, there is a mode that WILL allow the
uart to receive data while the cpu is asleep and you need to use
that mode to wake up on a character received. Of course the power
savings isn't as great with this mode.....
BTW, I'm working on a project with a mega128 avr using external
ram. In putting this one to sleep I first disabled external memory
mode so the chip select of the ram (wired to A15) would go high to
save the current pulled by the selected ram chip (dropped about
30ma!). But to do this I first had to relocate the stack to internal
ram (I'll leave the reason for this as an excerise for the reader!).
The stack is restored after the cpu wakes up. The cpu is put to sleep
in mainline code, ANY interrupt will wake up the cpu, and after
returning from interrupt we are at the instruction AFTER the sleep
instruction. NOTE that the interrupt code must NOT access any data
in external ram! (think of all the fun I am having with this!)
Reply by Meindert Sprang●July 20, 20052005-07-20
<ilovecpp@gmail.com> wrote in message
news:1121844978.458057.302820@g43g2000cwa.googlegroups.com...
> Thank you Meindert Sprang.
>
> But It's a little bit different. In my case, I fix code like below.
>
> void main(void)
> {
> Hardware_Init();
>
> while(1)
> {
> Uart_Put_Char('A');
> __asm volatile ("sleep");
> Uart_Put_Char('B');
> }
> }
>
> and My system doesn't print even "A".
That is most likely because you put the AVR to sleep before the "A" has left
the UART. Your Uart_Put_Char() first checks the UDRE bit, then it loads a
new byte in the UDR register. If you then call "sleep", the AVR goes to
sleep before the UART has finished shifting the byte out. Checking for UDRE
*after* the write to UDR doesn't help either because the UART is double
buffered. UDRE flags the state of the UDR register and not the shift
register. To test this, insert
while ( !( UCSRA & (1<<TXC)) );
before the "sleep" instruction. This will test if the shifter is really
empty and thus you have seen the "A" appear.
Meindert
Reply by ●July 20, 20052005-07-20
Thank you Meindert Sprang.
But It's a little bit different. In my case, I fix code like below.
void main(void)
{
Hardware_Init();
while(1)
{
Uart_Put_Char('A');
__asm volatile ("sleep");
Uart_Put_Char('B');
}
}
and My system doesn't print even "A".
I think something wrong.
Do you know why ?
Reply by Meindert Sprang●July 20, 20052005-07-20
<ilovecpp@gmail.com> wrote in message
news:1121840504.024790.82650@g14g2000cwa.googlegroups.com...
> Hi.
>
> I'd like to use sleep operation with USART but when I use USART with
> sleep operation, the system was crashed.
If you go to sleep mode, something has to happen to make the AVR wake up
from sleep mode. This is usually a reset or an interrupt. In your code, you
don't use interrupts on the UART, so when you enter sleep mode, the AVR
stays there.
Meindert
Reply by ●July 20, 20052005-07-20
Hi.
I'd like to use sleep operation with USART but when I use USART with
sleep operation, the system was crashed.
my code like this.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <stdio.h>
void Uart_Put_Char(unsigned char data)
{
while ( !( UCSRA & (1<<UDRE)) );
UDR = data;
}
void Hardware_Init(void)
{
MCUCR = 0xb0;
UBRRL = 16;
UCSRA = 0x00;
UCSRB = 0x18;
}
void main(void)
{
Hardware_Init();
while(1)
{
Uart_Put_Char('A');
__asm volatile ("sleep");
}
}
but when I comment like this
// __asm volatile ("sleep");
my code works fine.
I really wanna use sleep with USART.
Could you tellme why ?
thx.