mikrocontroller.net

Forum: Compiler & IDEs CPU verweigert den Schlaf


Autor: ceberus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok. Ich weiss ich bin jetzt besoffen und das ist auch gut so, darum mag 
man mir die Tippfehler verzeihen. Ich bastle seit Wochen an meinem Board 
rum um den CAN128 in den Schlaf zu versetzen, was mich inzwischen 3 oder 
mehr Wochenenden gekostet hat.
Das Ziel: Die CPU soll schlafen und sich aus einer kleinen Knopfzelle 
nähren wenn an PINE,PE7 ein Lowlevel anliegt und soll aus dem Schlaf 
zurückkehren, wenn PINE,PE7 wieder Spannung hat (High - Level), 
Natürlich soll dan noch immer die Uhrzeit stimmen. Es ist ein 32?Xde 
irgendwas am Port und das ASSR Register ist entsprechend eingestellt.

  // Oszillatoren einstellen
    setbit(ASSR,AS2);                  // 2. Oszillator für TOSC 
aktivieren
  // Clocktimer aktivieren
    TCCR2A = 0x05;                    // Prescaler Timer 2 = 128, extern 
32kHz Clock
    setbit(TIMSK2,OCIE2A);                // Interrupt enable Timer 2
  while(checkbit(ASSR,TCN2UB) || checkbit(ASSR,OCR2UB) || 
checkbit(ASSR,TCR2UB)) asm("NOP");

und ausgewertet wird auch ganz artig

SIGNAL(SIG_OUTPUT_COMPARE2)
  {
  setbit(GPIOR2,GPIOR01); // Sekundenbit
  }
wird gesetzt und die Uhrroutine arbeitet es ab, wenn Zeit dafür ist.
Ich habe zig Anleitungen und natürlich das vermaledeite Handbuch des CAN 
128 gelesen,  den Befehl asm(sleep) habe ich natürlich nirgendwo 
gefunden sondern bin in dem Programmbeispiel des Butterfly darüber 
gestolpert.
Da der Stromverbrauch im Sleep-Modus noch immer bei 10 - 12 mA lag hatte 
ich schon die Hardware in Verdacht... Heute dann die Ernüchterung.

Bei einem Codeschnipsel, der etwa diesem hier
clearbit(EIMSK,INT7);
  cli();
  SMCR = 0x0c;
  sleep_enable();
    sei();
  sleep_cpu();
  while(!checkbit(PINE,PE7)) {totzeitx++; asm volatile ("sleep");}

  sleep_disable();

  sei();

ähnlich gewesen sein könnte war totzeitx nach 3 Sekunden bei einer 
5stelligen Zahl. Es sollte dieses räudige 64beinige Mistvieh doch 
schlafen?! und nur jede Sekunde erwachen, wenn 
SIGNAL(SIG_OUTPUT_COMPARE2) klingelt. Wie kann es sich da in 3 Sekunden 
auf 27?x? hochschrauben?
Ergo. Die Sau schläft nicht. Ich bin mir nicht sicher ob ich überhaupt 
noch wissen will, warum das elende Mistvieh nicht schläft, aber 
vieleicht hat jemand eine Routine für mich wie ich den Hund zum schlafen 
bringe.
Prosit!

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ceberus wrote:
> Ergo. Die Sau schläft nicht.

Ja, der Powerdown Mode ist ziemlich tückisch.
Man muß eine bestimmte Abfolge einhalten und besonders auf die 
Interrupts achten.

Die WINAVR-Funktionen tragen auch das ihre zur Verwirrung bei, da sie 
nicht interruptfest sind.
Da steht zwar im "sleep.h" schön versteckt wichtiger Text, aber wer 
liest das schon so gründlich.

Am besten fährt man, wenn man sie daher nicht benutzt und alles selber 
macht.

Hier mal ein funktionierendes Beispiel auf nem ATtiny45:

http://www.mikrocontroller.net/attachment/33635/SLEEP.C


Peter

Autor: ceberus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach Peter, es ist ja nicht so, dass ich Deine Hilfen und Erklärungen 
nicht zu schätzen wüsste, auch wenn ich mir dabie immer vorkomme wie 
Alice im Wunderland.
Das Beispiel sieht ja auch schick aus, aber ???
Wie und wann kommt Dein Tiny aus der For-Schleife am Ende wieder raus? 
Und wo lässt man die Uhr?
Und wo ist jetzt eigentlich der elementare Fehler in meinem 
Geschriebsel? Macht es einen Unterscheid, ob ich das Register so SMCR = 
0x0c; oder MCUCR = 1<<SE^1<<SM1; beschreibe? wenn die 0 gesetzten Bits 
ohnehin nicht belegt sind?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ceberus wrote:

> Wie und wann kommt Dein Tiny aus der For-Schleife am Ende wieder raus?

Garnicht, das ist die Mainloop, da kommt nie ein MC raus.
Sie ist hier leer (außer dem Sleep), aber das ist ja nur ein 
Grundgerüst.


> Und wo lässt man die Uhr?

Im T2-Interrupt oder in der Mainloop.
Ganz wo Du willst.


> Und wo ist jetzt eigentlich der elementare Fehler in meinem
> Geschriebsel?

Daß es nur zusammenhanglose Codefetzen sind.


> Macht es einen Unterscheid, ob ich das Register so SMCR =
> 0x0c; oder MCUCR = 1<<SE^1<<SM1; beschreibe?

Ja, das letzte ist lesbarer.


Das Beispiel soll zeigen, daß es am sinnvollsten ist, die entsprechenden 
Sleepmodi in nem Interrupt zu setzen.
Dann muß das Main nur noch das eigentliche Sleep machen, wenn es alle 
Tasks fertig hat.
Wichtig ist, nur das nackte SLEEP, nicht das sleep_mode !!!

Es ergibt IMHO keinerlei Sinn, das Sleepenable separat von den 
Sleepmodis zu setzen. Entweder man will schlafen oder nicht.

Damit gibt es keine Konflikte mehr.


Peter

Autor: cerberus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun ja, ich hatte mir die Sache aus dem sleep.h zusammengeklaubt. 
Geholfen hat es nix. Warum das Sleep_enable immer separat gesetzt wurde, 
kann ich auch nicht sagen, ich habe es überall so gefunden und weil es 
bei mir nicht wirklich funktionierte, wenn ich es gleich mit geschrieben 
habe, habe ich es eben mal so herum probiert. Sleep im Interrupt, sleep 
ohne interrupt, sleep in der Endlosschleife, ... langsam gehen mir die 
Ideen aus...  Vermutlich muss ich es noch einmal ganz von Vorne anfangen 
und die komplette Software um das Sleep-Modul herumschreiben ...

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
cerberus wrote:

> Vermutlich muss ich es noch einmal ganz von Vorne anfangen
> und die komplette Software um das Sleep-Modul herumschreiben ...

Eigentlich nicht.
Man sollte erst die Funktionalität fertig stellen und das Sleep ganz zum 
Schluß dazubasteln.

Dazu braucht es nur eine Stelle im Main, wo man denkt, grad nichts mehr 
zu tun zu haben und dann das Sleep dahin setzen.
Das Sleep Mode einstellen machen dann die Interrupts oder das Main unter 
Interruptsperre.

Die Mainloop darf natürlich keine Delayschleifen enthalten, das würde ja 
einem Sleep zuwider laufen.
Also immer schön in Sleep gehen und Timerinterrupts aufsetzen für die 
Delays.


Peter

Autor: cerberus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich komme aus der SPS-Programmierung ;-) bei mir gibt es keine delays 
;-), wird alles über Merker gesteuert.
Das sleep in der Main-schleife und die Initialisierung in der ISR hatte 
ich gestern auch schon, hat aber auch nicht geholfen ...
Ich muss noch mal schauen, was passiert, wenn ich vorher alle Interrupts 
kille, bevor ich den Kollegen schlafen lege. Irgend wo da war ich 
gestern nicht mehr aufnahmefähig ... Ich weiss, dass er dann nicht mehr 
aufwacht, gerade das will ich ja wissen, oder ob er dann einfach 
sang-und Klanglos weitermacht.

Was denkst zu zu einem Main in der Form

int main( void )
{

// Initialisierung und vorgeplänkel

  while(1)
  {
   if(!checkbit(PINE,PE7))
     {
     totzeitx++;
     asm volatile ("sleep");
     }
   else
     {
// Hauptprogramm
     }
  }

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.