Sleep Mode + Pin Change Interrupt

Gast #4928383
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ß
Gast #4928418
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.
Gast #4928499
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...
Gast #4928608
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.
Gast #4928670
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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren