Moin zusammen,
ich habe jetzt schon die Wiki-Seiten von Mikrocontroller.net, sowie die
Erklärung in der sleep.h gelesen, doch irgendwie will mein uC nicht so
recht mit dem Schlafmodus:
Er geht zwar ohne Probleme in den Schlafmodus über, doch lässt sich
nicht mehr aufwachen. Das interessante ist, dass wenn ich mehrere Male
schnell hintereinander eine Taste (PCINT-Interrupt) drücke, dann kann es
sein, dass er den Tastendruck registiert, doch passiert das nur sehr
selten
Nebenbei benutze ich noch einen externen Uhrenquarz für eine RTC. Habe
ein Oszi mal an den Quarz gehalten und der schwingt auch noch wenn er im
Schlaf ist (Soll ja auch so sein!)
Meinen Source-Code findet ihr im Anhang.
Vielen Dank!
Marcel
Beschreib dochmal, wie das Programm ablaufen soll (Programmablaufplan),
insbesondere diese ganze Rum-Flag-serei.
Kommentare sind überhaupt nicht überflüssig, sie helfen einem selbst, in
seinen Programmen den Überblick zu behalten.
Peter
@ Marcel (Gast)
>sein, dass er den Tastendruck registiert, doch passiert das nur sehr>selten
Dein Programm ist etwas kryptisch. Vor allem ein cli() nach dem
et_sleep_mode(SLEEP_MODE_PWR_SAVE); sieht gefährlich aus. Und auch deine
Verwendung von sleep_enable, sleep_cpu etc. sieht chaotisch aus. Mach es
wie im Artikel Sleep Mode, und alles ist paletti.
MfG
Falk
Der Grund ist, dass ich nebenbei noch die Zeit zwischen 2Impulsen messe.
Wenn i=1 ist. Immer wenn ich eine Rising Edge habe, dann wird es auf 1
gesetzt. Wenn ich eine Falling habe, dann wieder auf 0.
Detektiere ich ein PCINT und passt der momentane Zustand nicht mit dem
gespeicherten i, kann nur einer der beiden Taster gedrückt worden sein.
Falk Brunner schrieb:> Dein Programm ist etwas kryptisch. Vor allem ein cli() nach dem> et_sleep_mode(SLEEP_MODE_PWR_SAVE); sieht gefährlich aus. Und auch deine> Verwendung von sleep_enable, sleep_cpu etc. sieht chaotisch aus. Mach es> wie im Artikel Sleep Mode, und alles ist paletti.
Ich habe mich hierbei aber genau an die Anweisung in der sleep.h
gehalten, die macht das wie folgt:
<http://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html>
1
#include<avr/interrupt.h>
2
#include<avr/sleep.h>
3
4
...
5
set_sleep_mode(<mode>);
6
cli();
7
if(some_condition)
8
{
9
sleep_enable();
10
sei();
11
sleep_cpu();
12
sleep_disable();
13
}
14
sei();
Peter Dannegger schrieb:> Beschreib dochmal, wie das Programm ablaufen soll (Programmablaufplan),> insbesondere diese ganze Rum-Flag-serei.
Ja da hast du Recht, etwas verwirrend ist das schon für einen
Außenstehenden.
1
/**
2
* Ort wo bitweise die Flags gespeichert werden - schneller Zugriff, da unter 0x1F!
3
*/
4
#define FLAG1_LOC GPIOR0
5
6
/**
7
* Wird gesetzt, wenn ein Impuls gekommen ist
8
*/
9
#define FLAG_IMPULS 2
10
11
/**
12
* Nach Entprellroutine - Taster1 (Weiter) gedrueckt
13
*/
14
#define FLAG_S1_PRESSED 3
15
16
/**
17
* Nach Entprellroutine - Taster2 (Bestaetigung) gedrueckt
18
*/
19
#define FLAG_S2_PRESSED 7
PS: Die Entprellroutine habe ich weitesgehend von dir übernommen :-).
Mit einer Ausnahme, dass ich diese nur aktiviere, wenn wirklich eine
Taste gedrückt wurde.
Also ich bin jetzt schonmal ein gutes Stück weitergekommen.
Habe die Entprellroutine rausgenommen und komischer weise registriert er
jetzt die Tastendrücke, aber unglaublich langsam. Er müsste jetzt
prellen und gleich 2/3 Tastendrücke registrieren, doch da tut sich mal
einer, wenn man lange draufdrückt. :(
Gibt es da etwa Probleme das der Taktgeber des uC gleich der Taktgeber
der RTC ist, denn wenn ich den internen Taktgeber als uC-Takt gebe, dann
läuft der Tastendruck wesentlich schneller.
Vielen Dank für eure Hilfe
Grüße!
Marcel
Ich arbeite lieber nach der Methode: teile und herrsche.
Ich würde den Sleep-Mode immer ganz zum Schluß implementieren, wenn die
anderen Funktionen alle fertig sind.
Der Timer2 im Async-Mode ist etwas tricky. Man muß nach jeder Aktion
erstmal testen, ob sie beendet wurde, ehe man in Sleep geht. Dazu gibt
es 3 Flags.
Auch ein Interrupt ist eine Aktion (Löschen des Interrupt-Flags), für
die es aber kein Updatebit gibt. Man muß dann ein Dummy-Write ausführen
und warten, bis dieses beendet ist.
Ich würde daher das Entprellen besser mit T0 oder T1 machen. Dann muß
man aber warten, bis das Entprellen der Aufwachtaste beendet ist:
1
uint8_tget_key_idle(uint8_tkey_mask)// check if ready for power down
2
{
3
return(KEY_PIN^key_state)&key_mask;
4
}
5
...
6
staticinlinevoidpower_down(void)
7
{
8
ATOMIC_BLOCK(ATOMIC_FORCEON){
9
if(get_key_idle(1<<KEY_ON_OFF)){// if debounce done