Atmega 644P schläft nicht!

Gast #1243908
Hier wurde mir schon sehr gut geholfen und ich hoffe auch hierfür eine 
Antwort zu bekommen! Ich habe ein minimales Programm geschrieben um zu 
gucken ob der ATmega 644P wirklich schlafen geht! Leider tut er es 
nicht! Kann mir jemand den Grund nennen?

#include<avr/io.h>
#include<avr/sleep.h>

int main()
{
     set_sleep_mode(SLEEP_MODE_PWR_SAVE);

     while(1)
     {
       sleep_cpu();
     }
     return(0);
}

Warum schläft er nicht?
Tommy wrote:

> Warum schläft er nicht?

Er schläft schon, bloß Du hast keinen Code drin, mit dem man es 
feststellen kann.
Setze z.B. ne PWM auf, die ne LED blinkt, dann merkst Du, ob die CPU den 
Takt anhält.

An der Stromaufnahme kannst Du es nicht feststellen, da in Deinen Code 
alle IO-Pins lustig vor sich hin floaten und so ordentlich Strom 
verbrauchen.


Peter
Gast
Bedeutet das, wenn ich ein besonders Stromsparendes Produkt bauen will, 
sollte ich alle nichtverwendeten PINS (PORTS) einen definierten Zustand 
geben? Ich dachte bei nicht aufgeführten Ports macht das der MC 
automatisch
Gast
Habe alle DDR Register auf Ausgang gestellt und alle PORTS auf 0x00.
Trotzdem bleibt die Stromaufnahme die selbe. Müsste sich nicht nach 
deiner Theorie der Stromfluß jetzt ändern?
Gast
Fangen wir mal vorne an: Wie misst du ob der mega schläft oder nicht? 
Strommessung mit irgendeiner Gurke? Strommessung in der komplett 
bestückten Schaltung?
Gast
>Ich verwende ein STK600 mit dem TQFP44 Adater. Vielleicht spielt das ja
>eine Rolle

Nimm den ATMega mal raus aus dem Board
und miss dann nochmal Strom ;)
Gast
Hab ich gemacht! Ich glaub ich verstehe! Die Einteilung meines Netzteils 
ist nicht gerade fein, sie schwankte zwischen 0.12 und 0.11 mA im 
Normabetrieb und wenn man genau im richtigen Moment hinguckt dann sieht 
man nur 0.11mA
Stellt man jetzt auf powersave dann verbleibt der Strom auf 0.11mA und 
schwankt nicht mehr.
Darus lässt sich schließen dass er in den Powersave Zustand geht, ich 
habs nur nicht richtig gesehen!

Mache es jetzt zusätzlich mit einer Uart und Leds, hab allerdings 
feststellen müssen, dass der Timer2 stehengeblieben ist, wenn ich 
sleep_cpu() eingebe!
Gast
So hab jetzt folgendes Programm geschrieben:

#include<avr/io.h>
#include<avr/interrupt.h>
#include<avr/sleep.h>
#include<util/delay.h>
#include"timer.h"
#include"uart.h"

#define F_CPU 4000000UL

// 9600 baud
#define UART_BAUD_RATE 9600

volatile uint8_t time=0;

ISR(TIMER2_OVF_vect)
{  time++;
}
int main()
{  DDRA=0xff;
  PORTA=0xff;
  set_sleep_mode(SLEEP_MODE_PWR_SAVE);
  sleep_enable();
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
//  uart1_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

  timer2_init();
  sei();
  while(1)
  {
    if(time==5)
    {
      uart_puts("Hello world");
      time=0;
    }
    else
      {
        PORTA=time;
    //    sleep_cpu();
      }
  }
  return(0);
}

So funktioniert das Programm einwandfrei, aber wenn ich sleep_cpu(); 
aktiviere bleibt der timer2() stehen! Hat jemand eine Idee?
Gast
>So funktioniert das Programm einwandfrei, aber wenn ich sleep_cpu();
>aktiviere bleibt der timer2() stehen! Hat jemand eine Idee?

Ist doch prima. Oder entspricht das nicht dem, was du erwartet hast?

Oliver
Gast
Hab jetzt mal auf Reset gedrückt und siehe da, er lief los. Aber es 
kommt kein Hello World über die Uart! Kann das Problem an falsch gesetzt 
Fuse Bits liegen? bzw. an diesem Fuse Bit:

Ext. Crystal Osc. 3.0-8Mhz Start-up time: 16KCK+65ms
Gast
>Ne! Timer2 müsste auch im Power Save Zustand weiterlaufen! Das zeichnet
>den timer2() bzw. den Power Save Modus aus.

Hast Recht. Da gabs bei den "alten" noch nicht.

>Hab jetzt mal auf Reset gedrückt und siehe da, er lief los. Aber es
>kommt kein Hello World über die Uart!

Mit welchem Takt läuft Timer 2, wenn er läuft?

Oliver
Gast
Die Artikel waren zwar sehr interessant aber wirklich weitegeholfen 
haben sie mir bei meinem Problem nicht!
Die Artikel dienen eher zur Stromoptimierung, was später auf jeden Fall 
eine Rolle spielen wird aber Momentan muss der MC erstmal überhaupt 
laufen.
Gast
#include<avr/io.h>
#include<avr/interrupt.h>
#include<avr/sleep.h>
#include"timer.h"
#include"uart.h"

#define F_CPU 4000000UL

// 9600 baud
#define UART_BAUD_RATE 9600

volatile uint8_t time=0;


#include<avr/io.h>
void timer2_init()
{
  ASSR|=(1<<EXCLK)|(1<<AS2);//externer Clock, asynchron Modus
//  ASSR|=(1<<AS2);//externer Clock, asynchron Modus
  TCCR2B|=(1<<CS22)|(1<<CS20);//takt durch 128 teilen
  TIMSK2|=(1<<TOIE2);  //timer overflow einschalten
}


ISR(TIMER2_OVF_vect)
{  time++;
}
int main()
{  DDRA=0xff;
  PORTA=0xff;
  set_sleep_mode(SLEEP_MODE_PWR_SAVE);
  sleep_enable();
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
//  uart1_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

  timer2_init();
  sei();
  while(1)
  {
    if(time==5)
    {
      uart_puts("Hello world");
      time=0;
    }
    else
      {
        PORTA=time;
        sleep_cpu();
      }
  }
  return(0);
}

Die Uart Routine hab ich jetzt mal weggelassen sonst wäre das Programm 
ein wenig zu groß für hier!
Gast
So, hab jetzt gelesen, wenn ich es richtig verstanden habe, dass man 
warten soll bis das TCN2UB Bit wieder 0 ist, hab es so realisiert!

#include<avr/interrupt.h>
#include<avr/sleep.h>
#include<util/delay.h>
#include"timer.h"
#include"uart.h"

#define F_CPU 4000000UL

// 9600 baud
#define UART_BAUD_RATE 9600

volatile uint8_t time=0;

ISR(TIMER2_OVF_vect)
{  while(ASSR|=(!(1<<TCN2UB)));
  time++;
}
int main()
{  DDRA=0xff;
  PORTA=0xff;
  set_sleep_mode(SLEEP_MODE_PWR_SAVE);
  sleep_enable();
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
//  uart1_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

  timer2_init();
  sei();
  while(1)
  {
    if(time==5)
    {//  while(ASSR|=(!(1<<TCN2UB)));
      uart_puts("Hello world");
      time=0;
    }
    else
      {
        PORTA=time;
        sleep_cpu();
      }
  }
  return(0);
}

Aber er kommt aus diesem while gar nicht mehr raus!
Welches while? Da sind zwei. Ich nehme an, es ist das while im Interrupt 
gemeint. Aber das betreffende Bit ist nur lesbar und das Assignment im 
while ohnehin einfach nur Mist.

Lies dir 14.9 nochmal genau durch. Notfalls mehrfach. Und in jedem 
Absatz nachdenken, ob dich das betrifft. Gibt da noch mindestens eine 
weitere Stelle.
Gast
Ich habe folgendes gefunden:

a. Write any value to either of the registers OCR2x or TCCR2x.
b. Wait for the corresponding Update Busy Flag to be cleared.
c. Read TCNT2.

Also ich verstehe das so z.B.

uint8_t test=0;
TCCR2B|=(1<<CS22)|(1<<CS20);
while(ASSR|=(1<<TCN2UB));
test=TCNT2;

Warum klappt das denn nicht? Was verstehe ich denn falsch?
Gast
Realisieren wollte ich es so:

include<avr/io.h>
#include<avr/interrupt.h>
#include<avr/sleep.h>
#include<util/delay.h>
#include"timer.h"
#include"uart.h"

#define F_CPU 4000000UL

// 9600 baud
#define UART_BAUD_RATE 9600

volatile uint8_t time=0;

ISR(TIMER2_OVF_vect)
{  uint8_t test=0;
  TCCR2B|=(1<<CS22)|(1<<CS20);//takt durch 128 teilen
  while(ASSR|=(1<<TCN2UB));
  test=TCNT2;
  time++;
}
int main()
{  uint8_t test=0;
  DDRA=0xff;
  PORTA=0xff;
  set_sleep_mode(SLEEP_MODE_PWR_SAVE);
  sleep_enable();
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

  timer2_init();
  sei();
  while(1)
  {
    if(time==5)
    {       uart_puts("Hello world");
      time=0;
    }
    else
      {
        PORTA=time;
        TCCR2B|=(1<<CS22)|(1<<CS20);
        while(ASSR|=(1<<TCN2UB));
        test=TCNT2;
        sleep_cpu();
      }
  }
  return(0);
}
Ich muss irgendetwas nicht verstanden haben! A. K. kannst du mir sagen 
was ich falsch mache?
Gast
Hab jetzt das while durch folgende Zeile ersetzt:

while (ASSR & (1 << TCN2UB) ) ;

Jetzt läuft der Quarz! Aber die Uart klappt noch nicht! Jedoch näher ich 
mich dem Ziel:)
14.9 dritter Absatz: "When entering Power-save or ADC Noise Reduction 
mode after having written to TCNT2, OCR2x, or TCCR2x, the user must wait 
until the written register has been updated...". Also auch in 
timer2_init() warten.
Gast
A. K. vielen Dank hab es ausprobiert und scheint zu klappen! Jedoch habe 
ich auch noch ein anderes Problem festgestellt. Das habe ich aber erst 
gesehen, als ich das JTAGICE mk2 angeschlossen habe. Wenn er in die 
Timer2 Interrrupt Routine reinspringt, führt er diese Routine mehrmals 
hintereinander druch.
Kann es sein, das man in dieser Routine auch warten muss, bis irgendein 
Interrupt Flag wieder Null geworden ist?

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.