Hallo, ich stehe hier gerade total auf dem Schlauch und hoffe ihr könnt mir weiterhelfen. Und zwar verwende ich einen atmega48 mit angeschlossenem Taster an PB5. Der Taster wird mit der "Comfortroutine" von Peter Danegger hier von der Seite entprellt/ausgewertet, was soweit auch wunderbar funktioniert. Nun möchte ich den Controller bei langem Tastendruck (get_key_long) in den Sleep-Modus versetzen und beim nächsten Mal Drücken per Pin-Change-Interrupt wieder ins Leben zurück holen. Jetzt besteht das Problem, dass der Controller zwar wie gewünscht in den Sleep-Modus versetzt wird, allerdings sofort beim loslassen der Taste wieder geweckt wird, da der Pin-Change-Interrupt auf beiden Flanken ausgelöst wird. Hoffe ihr versteht was ich meine. Wie kann ich das in meinem Programm verhindern? Probiere jetzt schon ewig daran rum aber bekomme es nicht wie gewünscht zum laufen :( Gruß
Tommi schrieb: > Wie kann ich das in meinem Programm verhindern? Probiere jetzt schon > ewig daran rum aber bekomme es nicht wie gewünscht zum laufen :( erst schlagen gehen, wenn Taste losgelassen wird.
Ja das hatte ich mir auch schon überlegt, scheint allerdings mit der Routine von Peter Dannegger nicht so einfach zu funktionieren, oder wie kann ich das realisieren? Wollte den MC zuerst beim Loslass-Interrupt schlafen legen, allerdings lässt er sich dann nicht mehr aufwecken.
1 | #define F_CPU 8e6/8
|
2 | |
3 | #include <avr/io.h> |
4 | #include <avr/interrupt.h> |
5 | #include <avr/sleep.h> |
6 | #include "debounce_2.h" // Peter Dannegger Routine |
7 | |
8 | typedef struct { // Flag Register |
9 | unsigned sleep:1; |
10 | } flagbytes; |
11 | volatile flagbytes flag; |
12 | |
13 | int main(void) |
14 | {
|
15 | //Sleep Mode und Pin Change zum Aufwecken
|
16 | PCICR |= (1<<PCIE0); |
17 | PCMSK0 |=(1<<PCINT5); |
18 | set_sleep_mode(SLEEP_MODE_PWR_DOWN); |
19 | |
20 | sei(); |
21 | |
22 | while(1) |
23 | {
|
24 | if(get_key_long(1<<KEY1)) |
25 | {
|
26 | flag.sleep=1; |
27 | }
|
28 | }
|
29 | }
|
30 | |
31 | ISR(PCINT0_vect) |
32 | {
|
33 | if(flag.sleep) |
34 | {
|
35 | flag.sleep=0; |
36 | sleep_mode(); |
37 | }
|
38 | }
|
Habe es jetzt mal so probiert, er geht jetzt beim Taster Loslassen zwar in den Schlafmodus, allerdings lässt er sich so nicht mehr aufwecken. Warum nicht? Bin Ratlos...
Dann leg ihn verzögert schlafen (nachdem die Taste losgelassen wurde und etliche Millisekunden verstrichen sind) mit Zählvariablen oder Timer...
Thomas E. schrieb: > Der Sleep-Aufruf darf nicht in einer ISR erfolgen. Das ist nicht ganz korrekt. Er darf schon in einer ISR erfolgen, aber nicht in exklusiv abgearbeiteten Code. Beim AVR8 ist das nicht synonym, da man jederzeit in einer ISR "sei" ausführen kann, womit man zwar nach wie vor innerhalb einer ISR ist, aber nicht mehr in nicht unterbrechbarem Code.
Thomas E. schrieb: > Tommi schrieb: >> Warum nicht? Bin Ratlos... > > Der Sleep-Aufruf darf nicht in einer ISR erfolgen. Danke! Jetzt geht es. Hier nochmal der Code:
1 | if(get_key_long(1<<KEY1)) |
2 | {
|
3 | sleep_state=1; //Schlafen legen |
4 | PCICR |= (1<<PCIE0); |
5 | PCIFR |= (1<<PCIF0); |
6 | }
|
7 | if(sleep_state==2) |
8 | {
|
9 | sleep_state++; |
10 | PCICR |= (1<<PCIE0); |
11 | PCIFR |= (1<<PCIF0); |
12 | PORTD=0xFF; |
13 | sleep_mode(); |
14 | }
|
15 | |
16 | |
17 | ISR(PCINT0_vect) |
18 | {
|
19 | if(sleep_state==1) |
20 | {
|
21 | // Im Hauptprogramm schlafen legen
|
22 | sleep_state++; |
23 | }
|
24 | else if(sleep_state==3) |
25 | {
|
26 | // Grade aufgewacht
|
27 | set_display_number(bpm); |
28 | wait_cnt=1; |
29 | }
|
30 | PCICR &=~ (1<<PCIE0); |
31 | PCIFR |= (1<<PCIF0); |
32 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.