Atmega 644P schläft nicht!

Gast #1243908
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?
#1243918
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
Gast #1243992
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!
Gast #1244030
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?
Gast #1244104
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
Gast #1244122
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!
Gast #1244219
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!
Gast #1244285
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?
Gast #1244300
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?
Gast #1245036
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren