AVR Sleep und Button Interrupt

OP #7468415
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.)

Angehängte Dateien:
#7468441
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.

OP #7475165
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.

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

#7475237
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').

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