Forum: Mikrocontroller und Digitale Elektronik Sleep Mode + Pin Change Interrupt


von Tommi (Gast)


Lesenswert?

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ß

von Peter II (Gast)


Lesenswert?

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.

von Thomas E. (thomase)


Lesenswert?


von Tommi (Gast)


Lesenswert?

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.

von Tommi (Gast)


Lesenswert?

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...

von uwe (Gast)


Lesenswert?

Dann leg ihn verzögert schlafen (nachdem die Taste losgelassen wurde und 
etliche Millisekunden verstrichen sind) mit Zählvariablen oder Timer...

von Thomas E. (thomase)


Lesenswert?

Tommi schrieb:
> Warum nicht? Bin Ratlos...

Der Sleep-Aufruf darf nicht in einer ISR erfolgen.

von c-hater (Gast)


Lesenswert?

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.

von Tommi (Gast)


Lesenswert?

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
}

von Peter D. (peda)


Lesenswert?


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
Noch kein Account? Hier anmelden.