Hi!
Ich habe folgendes Problem:
Beim Auftreten einer fallenden Flanke an einem externen Interrupt
Eingang (INT6), soll der µC in den Power-Down Modus gehen. Soweit so
gut, das klappt alles
Nun will ich aber, dass er mir bei einer steigenden Flanke wieder zu
leben zieht. Laut Datenblatt S.90 steht da folgendes:
"Low level interrupts and the edge interrupt on INT3:0 are detected
asynchronously. This implies that these interrupts can be used for
waking the part also from sleep modes other than Idle mode. The I/O
clock is halted in all sleep modes except Idle mode."
sowie
"Note that if a level triggered interrupt is used for wake-up from
Power-down mode, the changed level must be held for some time to wake up
the MCU. This makes the MCU less sensitive to noise."
Fürs Wecken verwende ich INT2, demnach müsste das doch eigentlich
klappen?
Kann mir einer sagen, warum es trotzdem nicht geht? Können nur fixe
Logische Pegel den µC wieder aufwecken?
Vielen Dank und schöne Grüße
Philipp
Philipp Putzer wrote:
> Kann mir einer sagen, warum es trotzdem nicht geht? Können nur fixe> Logische Pegel den µC wieder aufwecken?
Im Power-Down-Modus ist der CPU-Takt deaktiviert. Für einen
Flanken-Interrupt wird dieser aber benötigt. Deshalb steht im
entsprechenden Abschnitt im Datenblatt auch, dass nur ein externer
*Level*-Interrupt den µC aus dem Power-Down aufwecken kann, weil ein
Level-Interrupt keinen Takt zur Synchronisation benötigt.
Johannes M. wrote:
> Philipp Putzer wrote:>> Kann mir einer sagen, warum es trotzdem nicht geht? Können nur fixe>> Logische Pegel den µC wieder aufwecken?> Im Power-Down-Modus ist der CPU-Takt deaktiviert.
Hmmm... - Der (der CPU-Takt) ist bei Idle auch deaktiviert. ;-)
Daher hat der Takt, der für I/O zuständig ist, vermutlich einen anderen
Namen, sorry. Aber ansonsten ist das alles richtig.
> Für einen> Flanken-Interrupt wird dieser aber benötigt. Deshalb steht im> entsprechenden Abschnitt im Datenblatt auch, dass nur ein externer> *Level*-Interrupt den µC aus dem Power-Down aufwecken kann, weil ein> Level-Interrupt keinen Takt zur Synchronisation benötigt.
...
Philipp Putzer wrote:
> Fürs Wecken verwende ich INT2, demnach müsste das doch eigentlich> klappen?
Upps, das hatte ich doch beim ersten Mal glatt übersehen... Mit INT2
müsste es tatsächlich klappen, weil der (wie auch INT3, 1 und 0)
asynchron detektiert wird. Hatte gedacht, Du wolltest ihn auch mit INT6
wieder zurückholen... Also wie gesagt, mit INT2 müsste es eigentlich
auch auf Flanke klappen.
@Hannes:
Hast natürlich recht, sollte I/O-Takt anstelle von CPU-Takt heißen (bzw.
der eigentliche Hauptunterschied zum Idle ist eben, dass der
Hauptoszillator komplett abgeschaltet wird...)
Eben, es müsste ja eigentlich klappen
Auf S.48 in der Tabelle für die Weckquellen aus den verschiedenen
sleep-modi steht ja auch bei wake up source, INT3:0 or level interrupt
INT4:7. Da denke ich kann jedes INT3:0 gehen.
Wenn ich den Eintritt in den Power-down auskommentiere, funkt mein Int2
einwandfrei mit der steigenden Flanke. Nur weckt es den nicht mehr auf!
Kann es damit zu tun haben, dass die Fuses für die Warmlaufzeit nicht
richtig gesetzt sind? Bei mir sind CKSEL3:0, SUT1:0 programmiert (16MHz
externer Quarz)
Nein, damit kann es nicht zu tun haben, das ist dem Controller egal. Er
braucht halt die eingestellte Zeit, um wieder anzufahren, mehr nicht.
>Wenn ich den Eintritt in den Power-down auskommentiere, funkt mein Int2>einwandfrei mit der steigenden Flanke. Nur weckt es den nicht mehr auf!
Dann ist dort irgendetwas nicht korrekt. Oder aber in der
Initialisierung des Sleep-Modes. Wie ist denn der Zustand Deines
Int-Pins vor dem Eintritt in den Tiefschlaf? Zeit, etwas Code zu posten!
Anbei der Code.
Beim INT6 hängt ein TTL Ausgang eines Komperators, der bei Abfall der
Betriebsspannung unter 9V auf Masse schaltet (fallende Flanke also)
Damit geht gleichzeitig der INT2 auf High, und belibt da so lange, bis
a) der Komp. wieder in den ursprünglichen Zustand schaltet
b) eine andere Versorgung angeschlossen wird
Trifft a oder b zu, dann tritt eine fallende Flanke am INT2 auf, und
soll den µC wecken.
Kann auch nicht klappen, weil Du in der ISR den sleep-Befehl ausführst.
Zu dem Zeitpunkt ist aber das I-Bit im SREG gelöscht und damit ist die
Bearbeitung sämtlicher Interrupts gesperrt. Dementsprechend kann der
INT2 gar nicht auslösen. Ein nicht freigegebener Interrupt kann nunmal
den µC nicht aufwecken. Du musst entweder das sleep_mode() im
Hauptprogramm ausführen (empfohlene Vorgehensweise) oder aber (etwas
weniger empfehlenswert) das I-Bit in der INT6-ISR vor dem sleep_mode()
wieder setzen.
Ich hoffe, Du siehst jetzt endlich auch, wie wichtig es ist, den Code zu
posten. Hätte ich das sofort gesehen, dann wäre Dein Problem vermutlich
längst gelöst...
Stimmt! OK, daran hatte ich nun glatt nicht gedacht
Ich werds dann mal heute abend testen, mit ausführung des sleep modes im
Hauptprogramm!
Vielen, vielen Dank auch!