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


von Tommy (Gast)


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?

von Peter D. (peda)


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

von Tommy (Gast)


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

von Tommy (Gast)


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?

von (prx) A. K. (prx)


Lesenswert?

Watchdog aktiv?

von Tommy (Gast)


Lesenswert?

Ne auch nicht!

von Michael U. (amiga)


Lesenswert?

Hallo,

ich vermisse sleep_enable();

Sonst schläft da nichts.

Gruß aus Berlin
Michael

von Norgan (Gast)


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?

von Tommy (Gast)


Lesenswert?

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

von holger (Gast)


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 ;)

von Tommy (Gast)


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!

von Tommy (Gast)


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?

von Oliver (Gast)


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

von Tommy (Gast)


Lesenswert?

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

von Tommy (Gast)


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

von .... (Gast)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

Siehe Sleep Mode

von Oliver (Gast)


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

von Tommy (Gast)


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.

von Oliver (Gast)


Lesenswert?

>Siehe Sleep Mode

hab ich jetzt mal entsprechend erweitert.

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

Zeig mal den ganzen Code.

Oliver

von Tommy (Gast)


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!

von Tommy (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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

von Tommy (Gast)


Lesenswert?

Ich weiß nicht genau was du meinst!

von (prx) A. K. (prx)


Lesenswert?

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

von Tommy (Gast)


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!

von (prx) A. K. (prx)


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.

von Tommy (Gast)


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?

von Tommy (Gast)


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?

von Tommy (Gast)


Lesenswert?

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

von Tommy (Gast)


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:)

von Tommy (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


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.

von Tommy (Gast)


Lesenswert?

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

von Tommy (Gast)


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?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.