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
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
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?
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?
>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 ;)
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!
>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
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
>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
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.
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.
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?
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.
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?