mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega 644P schläft nicht!


Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Watchdog aktiv?

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ne auch nicht!

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich vermisse sleep_enable();

Sonst schläft da nichts.

Gruß aus Berlin
Michael

Autor: Norgan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch mit sleep_enable() tut sich nichts!
Ich verwende ein STK600 mit dem TQFP44 Adater. Vielleicht spielt das ja 
eine Rolle

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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 ;)

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ne! Timer2 müsste auch im Power Save Zustand weiterlaufen! Das zeichnet 
den timer2() bzw. den Power Save Modus aus.

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: .... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja. Es gibt da noch ein paar Bits, mit denen man den Powersave 
konfigurieren kann. Steht aber alles im Datenblatt.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Sleep Mode

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Siehe Sleep Mode

hab ich jetzt mal entsprechend erweitert.

>aber Momentan muss der MC erstmal überhaupt
>laufen.

Zeig mal den ganzen Code.

Oliver

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#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!

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe jetzt mal von der JTAG Programmierung in die ISP Programmierung 
gewechselt, ändert sich aber auch nichts!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dass der Timer im asynchronen Modus besonderen Regeln unterliegt, 
Interrupt inklusive, das hast du im Manual bestimmt genau durchgelesen?

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß nicht genau was du meinst!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kapitel 14.9. Sind 1,5 Seiten darüber, was dabei anders funktioniert als 
gewohnt. Auch was den Power-Save Modus angeht.

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ups, ich setze ja mit dem while das ASSR und ich warte ja nicht!

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:)

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Muss es wieder zurücknehmen! Erfunktioniert zwar aber nicht immer!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. vielen Dank! Werde es gleich morgen ausprobieren muss jetzt leider 
aufhören! Aber Danke noch mal

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.