Forum: Mikrocontroller und Digitale Elektronik AVR Sleep und Button Interrupt


von Georg M. (g_m)


Angehängte Dateien:

Lesenswert?

Hallo.

Ich hatte einen funktionierenden Code um eine kleine Zusatzfunktion 
erweitert: Mit einem kleinen Taster sollte geprüft werden können, ob die 
Akkuspannung unter 3,5 V liegt. Die Änderung war jedoch fehleranfällig 
und das Aufwachen wurde unzuverlässig.

Nun habe ich den Code so weit wie möglich reduziert und den Fehler 
gefunden:
die Zeile
1
PORTA.PIN2CTRL = PORT_PULLUPEN_bm | PORT_ISC_LEVEL_gc;
muss unmittelbar vor der Anweisung
1
sleep_mode();
stehen.

Aber warum der etwas andere Code nicht funktioniert, verstehe ich immer 
noch nicht.

Auch habe ich Schwierigkeiten zu erkennen, inwieweit das Prellen den 
Fehler verursacht, bzw. an welcher Stelle im Code die Entstehung des 
Fehlers offensichtlich wird.

Außerdem wollte ich fragen, ob hier die Deklaration "volatile" 
überflüssig ist oder notwendig.

Vielen Dank im Voraus.


(Die Codes im Anhang sind die reduzierten Codes, keine eigenständigen 
Codes, können daher einen unvernünftigen Eindruck machen.)

von Peter D. (peda)


Lesenswert?

Schau mal in die "sleep.h":
"the sleep_mode() macro might cause race conditions in some situations"
Wenn da der Aufwachinterrupt reinhaut, wars das.
Nimm besser das sleep_cpu(); wie im Beispiel.
Das sleep_disable(); ist Mumptiz und sollte entfallen. Dann reicht auch 
das sleep_enable(); einmalig im Init-code.

von Georg M. (g_m)


Lesenswert?

Peter D. schrieb:
> Schau mal in die "sleep.h":
> "the sleep_mode() macro might cause race conditions in some situations"
> Wenn da der Aufwachinterrupt reinhaut, wars das.
> Nimm besser das sleep_cpu(); wie im Beispiel.
> Das sleep_disable(); ist Mumptiz und sollte entfallen. Dann reicht auch
> das sleep_enable(); einmalig im Init-code.

Ich kann auf <avr/sleep.h> komplett verzichten. Aber der Programmfehler 
wird dadurch nicht behoben. Ich muss den Taster nur noch viel öfter 
drücken, bis der Fehler auftritt und der Mikrocontroller nicht mehr 
aufwacht.

von Peter D. (peda)


Lesenswert?

Ich muß zugeben, ich seh da nicht durch, wie Du die Taste auswertest.

Ich benutze eine völlig andere Herangehensweise. Der Aufwachinterrupt 
macht nichts weiter, als nur aufwachen (Empty Interrupt).
Das Tasten entprellen erfolgt dann in der üblichen Weise im 
Timerinterrupt.
Das Schlafen gehen wird über ein Flag gesteuert.

Damit auch wirklich kein Aufwachen durch die Lappen geht, wird der 
Interrupt erst direkt vor dem Sleep enabled und danach sofort wieder 
disabled.
Damit wird garantiert, daß das ein Pin-Change-Interrupt erst nach dem 
Sleep ausgeführt werden kann bzw. ein erneutes Pin-Change bis zu 
nächsten Sleep gespeichert bleibt.

Beitrag "Re: AVR Sleep Mode / Knight Rider"

Um welchen AVR geht es eigentlich?
Den genauen MC sollte man immer mit angeben.

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

1
    if(tcb)                                                    // TCB for debouncing without delay
2
    {
3
      if(PORTA.IN & PIN2_bm)                                   // if PA2 button released
4
      {
5
        PORTA.OUTCLR = PIN1_bm;                                // PA1 off
6
        tcb = 0;                                               // clear the flag
7
        indicate = 0;                                          // clear the flag
8
        PORTA.PIN2CTRL = PORT_PULLUPEN_bm | PORT_ISC_LEVEL_gc; // PA2 pull-up, low level sense interrupt
9
* <------------
10
      }
11
    }
12
    if(!indicate)
13
    {
14
* <------------
15
      sleep_mode();
16
    }

Wenn zwischen den markierten Stellen ein Taster-Interrupt auftritt, dann 
kann der uC nicht mehr aufwachen.

PS:
Denn in der ISR wird die Interrupt-Fähigkeit abgeschaltet (im Gegensatz 
zum 'workable code').

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

S. L. schrieb:
> if(!indicate)

Stimmt, eine C-Zeile ist oft nicht atomar.
Hier dürften es 3 Befehle sein (Laden, Vergleichen, bedingter Sprung), 
wo ein Interrupt prima dazwischen funken kann.

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.