Ich komme nicht weiter und bitte um Hilfe.
Ich möchte einen At328p in den Schlafmodus versetzen und nach 60
Sekunden wieder aufwecken. Timer2 zählt, solange der Atmega nicht im
Schlafmodus ist.
Am Timer2 hängt ein 32.768Khz Uhrenquarz.
Sobald ich:
----------schnipp-------------
set_sleep_mode(SLEEP_MODE_PWR_SAVE);
sleep_mode(); // in den Schlafmodus wechseln
---------schnapp--------------
aktiviere, bleiben die LED's für immer dunkel.
Was mache ich falsch?
Danke im Vorraus.
1 | void timer2_init(void)
| 2 | {
| 3 | ASSR = (0<< AS2); // Timer2 asynchron takten
|
?
0 geshiftet um was_weiß_ich_was ist immer suspekt.
Laut Datenblatt willst du das Bit allerdings auf 1 haben, um den Timer
auf asynchron zu schalten. Und nur dann kommst du auch aus dem Power
Save wieder raus.
Stefan B. schrieb:
> Sobald ich:
> ----------schnipp-------------
> set_sleep_mode(SLEEP_MODE_PWR_SAVE);
> sleep_mode(); // in den Schlafmodus wechseln
> ---------schnapp--------------
> aktiviere, bleiben die LED's für immer dunkel.
Und so ? 1 | ----------schnipp-------------
| 2 | set_sleep_mode(SLEEP_MODE_PWR_SAVE);
| 3 | ///////////////////////////////
| 4 | sleep_enable(); // MCUCR mitteilen, was du vorhast
| 5 | //////////////////////////////
| 6 | sleep_mode(); // in den Schlafmodus wechseln
| 7 | ---------schnapp--------------
|
Karl Heinz schrieb:
> 0 geshiftet um was_weiß_ich_was ist immer suspekt.
Oha, ja, das war ein Fehler....
Ich habs jetzt auf: ASSR = (2<< AS2); geändert.
Marc Vesely schrieb:
> sleep_enable();
Habs mal eingebaut, funktioniert aber trotzdem nicht.
Es wäre auch möglich gewesen, dass die Sekunden >=60 nicht auf Null
gesetzt werden, ist aber auch nicht der Fall.
Ich hab beim µc den Wecker mal bei Sekunde 59 klingeln lassen. Die LED's
bleiben trotzdem dunkel.
Stefan B. schrieb:
> Karl Heinz schrieb:
>> 0 geshiftet um was_weiß_ich_was ist immer suspekt.
>
> Oha, ja, das war ein Fehler....
>
> Ich habs jetzt auf: ASSR = (2<< AS2); geändert.
Tippfehlere hier im Forum, oder warum die 2?
Ich glaube, ich komme der Sache näher.
Nein, das war kein Tippfehler. Hab nochmal nachgesehen.
So stehts jetz drin: ASSR = (1<< AS2);
Allerdings zählt jetzt der Timer nichtmehr.
Ähhm, Hardware kanns nicht sein, ich habe vorhin das ganze mit nem
Atmega8 getestet, da funktioniert es. Nur funzt der Atmega8 nicht unter
2,7 Volt.
Ich habe es jetzt so gelöst, indem ich den Atmega8L erstmal verwende,
bis ich ne Lösung zum Atmega328p-Problem gefunden habe.
Der Vollständigkeit halber im Anhang noch das main-File vom Atmega8L.
Grüße....
Stefan B. schrieb:
> Ich habe es jetzt so gelöst, indem ich den Atmega8L erstmal verwende,
> bis ich ne Lösung zum Atmega328p-Problem gefunden habe.
Hoffentlich.
Mir erschliesst sich sich zwar nicht, warum du ständig die Interrupts
abschaltest, aber wenn schon, dann solltest du sie auch wieder
einschalten.
1 | void read_adc (void)
| 2 | {
| 3 | sei(); //Activate interrupts
| 4 | setup_adc();
| 5 | cli();
| 6 | }
|
Ich kann beim besten Willen die Stelle nicht finden, wo sie wieder
eingeschaltet werden. Dann kannst du natürlich lange auf deine
Timerinterrupts warten.
Im Gegensatz dazu hast du das beim 8er aber gemacht:
1 | void schlafmodus (void)
| 2 | {
| 3 | sei();
| 4 | set_sleep_mode(SLEEP_MODE_PWR_SAVE);
| 5 | sleep_enable();
| 6 | sleep_mode();
| 7 | sleep_disable();
| 8 | cli();
| 9 | }
|
während du den 328er nicht schlafen, sondern ins Koma schickst:
1 | set_sleep_mode(SLEEP_MODE_PWR_SAVE);
| 2 | sleep_mode();
|
Ein sleep_enabale(); hab ich auch nirgends gesehen.
mfg.
PS: Den Code vernünftig einrücken, sieht nicht nur hübscher aus, sondern
liest sich auch besser.
Stefan B. schrieb:
> Der Vollständigkeit halber im Anhang noch das main-File vom Atmega8L.
1 | void schlafmodus (void)
| 2 | {
| 3 | sei();
| 4 | set_sleep_mode(SLEEP_MODE_PWR_SAVE);
| 5 | sleep_enable();
| 6 | sleep_mode();
| 7 | sleep_disable();
| 8 | cli();
| 9 | }
|
Ich würde es so probieren: 1 | sleep_enable();
| 2 | set_sleep_mode(SLEEP_MODE_PWR_SAVE);
| 3 | sei();
| 4 | sleep_cpu(); //Put the device into sleep mode. The SE bit must be set
| 5 | // beforehand, and it is recommended to clear it afterwards.
| 6 | sleep_disable();
| 7 | cli();
|
Da ich nicht weiß, was GCC genau macht, kann ich auch nicht behaupten,
dass das funktioniert, aber es scheint irgendwie logischer.
Das ganze in Assembler zu schreiben, wäre viel besser, zumindest bis
es fehlerfrei läuft.
Marc Vesely schrieb:
> sleep_enable();
> set_sleep_mode(SLEEP_MODE_PWR_SAVE);
> sei();
> sleep_cpu();
> sleep_disable();
> cli();
Warum so kompliziert?
1 | int main(void)
| 2 | {
| 3 | set_sleep_mode(SLEEP_MODE_PWR_SAVE);
| 4 | sleep_enable();
| 5 | .
| 6 | .
| 7 | .
| 8 | sei();
| 9 |
| 10 | while()
| 11 | {
| 12 | .
| 13 | .
| 14 | .
| 15 | if(SleepAllowed)
| 16 | {
| 17 | sleep_cpu();
| 18 | SleepAllowed = 0;
| 19 | }
| 20 | .
| 21 | .
| 22 | }
| 23 | }
|
Und die Interrupts werden einmal eingeschaltet und bleiben das auch.
Marc Vesely schrieb:
> Das ganze in Assembler zu schreiben, wäre viel besser, zumindest bis
> es fehlerfrei läuft.
Unsinn.
mfg.
Thomas Eckmann schrieb:
> Unsinn.
Und warum ?
Weil das ganze nur auf paar bits setzen und rücksetzen hinausläuft ?
Marc Vesely schrieb:
> Weil das ganze nur auf paar bits setzen und rücksetzen hinausläuft
Und das geht in C nicht?
Ausserdem habe ich geschrieben, wie man es richtig macht.
Friggel weiter!
Erstmal danke für die Tips.
Thomas Eckmann schrieb:
> Mir erschliesst sich sich zwar nicht, warum du ständig die Interrupts
> abschaltest, aber wenn schon, dann solltest du sie auch wieder
> einschalten.
Das ändere ich morgen noch.
Thomas Eckmann schrieb:
> während du den 328er nicht schlafen, sondern ins Koma schickst:
> set_sleep_mode(SLEEP_MODE_PWR_SAVE);
> sleep_mode();
>
> Ein sleep_enabale(); hab ich auch nirgends gesehen.
Das Problem ist beim 328er, dass der Timer schon garnicht mit dem im
ersten Beitrag angehängten C-File läuft und ich habe bis jetzt den
Fehler noch nicht gefunden.
irgendwo hier drin ist für den 328er noch ein Fehler:
void timer2_init(void)
{
ASSR = (1<< AS2); // Timer2 asynchron takten
long_delay(1000); // Einschwingzeit des 32kHz Quarzes
TCCR2A = (1<<WGM21); // CTC-Modus
TCCR2B = (1<<CS22)|(1<<CS20); // Vorteiler=128
while((ASSR & (1<< TCR2AUB))); // Warte auf das Ende des Zugriffs
TIFR2 = (1<<OCF2A); // Interrupt löschen (*)
TIMSK2 |= (1<<OCIE2A); // Timer Compare Match Interrupt
freischalten
// (*) "Alternatively, OCF2 is cleared by writing a logic one to the
flag."
OCR2A=NormalerCompwert;
while((ASSR & (1<< OCR2AUB))); // Warte auf das Ende des Zugriffs
}
Falk Brunner schrieb:
> Siehe Sleep Mode.
Hi Falk, ähhm, habe ich schon mehrfach durchgelesen.
Thomas Eckmann schrieb:
> Warum so kompliziert?
> int main(void)
> {
> set_sleep_mode(SLEEP_MODE_PWR_SAVE);
> sleep_enable();
> .
Danke Thomas, das probiere ich morgen mal aus.
Aber mein größtes Problem ist, dass die ganze Geschichte nicht auf dem
328er funktionieren will. Ich würde den lieber benutzen als den Atmega8,
da wie gesagt, beim Atmega8 bei unter 2.7 Volt schluss ist und der 328er
funzt noch mit 1.7 Volt.
Thomas Eckmann schrieb:
> Ausserdem habe ich geschrieben, wie man es richtig macht.
Ich bewundere deine C-kenntnisse.
Wahrscheinlich schon hart an der Grenze mit diesem (abgeschriebenem)
Schnipsel. Viel weiter wirst du eh nicht kommen.
Warum denn immer diese Stichelei?
Ich persönlich hätte auch nie gedacht, dass ich anfangs mit meinen
nullkommanull-Kenntnissen überhaupt soweit komme....hehe
Marc Vesely schrieb:
> Viel weiter wirst du eh nicht kommen.
Ach Vesy, YMMD
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|