Forum: Mikrocontroller und Digitale Elektronik Interrupt Atmega 328P


von Flor B. (florben)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

vielleicht kann mir jemand bei meinem Programm Problem helfen.

Eigentlich soll je nach dem welcher Taster(PB0 bis PB2 ) gedrückt wurde
eine LED (PC0 bis PC2) eingeschaltet werden. Das ganze soll über einen
jeweiligen Interrupt ausgelöst werden.

Allerdings wird nur die  ISR (PCINT0_vect) aufgerufen. Egal welchen
Taster ich drücke.

Hab ich hier einen Denkfehler?

von Thomas E. (thomase)


Lesenswert?

Flo. W. schrieb:
> Hab ich hier einen Denkfehler?

Einen gewaltigen.

Die PC Ints beziehen sich immer auf den ganzen Port. Hast du mehrere 
Pins eines Ports maskiert, musst du in der ISR oder an sonst einer 
geeigneten Stelle gucken, welcher es war.

Aber Taster und Interrupt ist sowieso nicht so toll. Normalerweise wird 
man in diesem Forum dafür gesteinigt. Frag die Taster mittels Timer ab 
und entprell sie vernünftig. Sonst wirst du damit ohnenhin kein Freude 
haben.

Wie man das richtig macht, kannst du im Tutorial nachlesen.

: Bearbeitet durch User
von Flor B. (florben)


Lesenswert?

Danke für die schnelle Hilfe.

Dann werde ich mir mal das Tutorial anschauen.

von Stefan F. (Gast)


Lesenswert?

Ich verstehe den Text im Datenblatt jedoch anders:

"Each PCINT7..0 bit selects whether pin change interrupt is enabled on 
the corresponding I/O pin. If PCINT7..0 is set and the PCIE0 bit in 
PCICR is set, pin change interrupt is enabled on the corresponding I/O 
pin. If PCINT7..0 is cleared, pin change interrupt on the corresponding 
I/O pin is disabled."

Da steht nichts von ganzen Ports.

Allerdings bestätigt dieses Tutorial, was "Thomas Eckmann" geschrieben 
hat:

https://thewanderingengineer.com/2014/08/11/arduino-pin-change-interrupts/

von Thomas E. (thomase)


Lesenswert?

Stefan U. schrieb:
> Da steht nichts von ganzen Ports.

Darum geht es ja auch nicht.

1 bis 8 Pins an PORTx, je nachdem, welche maskiert sind, lösen ein und 
den selben Interrupt aus. Nämlich den, der zu diesem Port gehört.

von Stefan F. (Gast)


Lesenswert?

Ja, habe ich (nach dem Lesen des Tutorials) auch so verstanden. Das 
Datenblatt finde ich in dieser Hinsicht sehr unklar, da könnte man 
meinen, daß PCINT1 zum gleichnamigen Pin gehört.

Wenn man beim Ausprobieren mit PCIN0 anfängt, merkt man nichtmal den 
Irrtum. Das ist echt fies!

von Thomas E. (thomase)


Lesenswert?

Stefan U. schrieb:
> Das ist echt fies!

Ja, dem kann man zustimmen. Zumindest ist es unglücklich.

von S. Landolt (Gast)


Lesenswert?

Der Sachverhalt wird spätestens dann klar, wenn man die dazugehörenden 
Interruptvektoren sucht und feststellt, dass es beim ATmega328 davon nur 
drei gibt.

von Walter S. (avatar)


Lesenswert?

Stefan U. schrieb:
> Da steht nichts von ganzen Ports.

da nicht, aber z.B. da:
Pin Change Interrupt PCI0 triggers if a pin in PCINT[7:0] is toggled 
while enabled

von batman (Gast)


Lesenswert?

Kann man überhaupt sicher feststellen, von welchem Pin der IRQ ausgelöst 
wurde, oder hat sich der Pinzustand dann vielleicht schon geändert, wenn 
der ISR-Code startet?

von spess53 (Gast)


Lesenswert?

Hi

>Kann man überhaupt sicher feststellen, von welchem Pin der IRQ ausgelöst
>wurde, oder hat sich der Pinzustand dann vielleicht schon geändert, wenn
>der ISR-Code startet?

Klar man muss nur den Stand bei jeden Interrupt Speichern. Dann reicht 
ein einfaches XOR.

MfG Spess

von Thomas E. (thomase)


Lesenswert?

batman schrieb:
> Kann man überhaupt sicher feststellen, von welchem Pin der IRQ
> ausgelöst
> wurde, oder hat sich der Pinzustand dann vielleicht schon geändert, wenn
> der ISR-Code startet?

Das ist genau das Problem, wenn man Taster ohne Entprellung abfragt und 
sich nur auf den INT verlässt. Bei einem Taster bräuchte man ja nicht 
einmal nachgucken, welcher es war. Der INT könnte aber auch von einem 
sehr kurzen Störsignal ausgelöst worden sein.

In der Praxis hat es sich daher bewährt, den oder mehrere PCINT nur zum 
Aufwecken des Controllers aus dem Sleep Mode zu benutzen, danach die 
PCINTs abzuschalten und die normale Entprellung ablaufen zu lassen. Nach 
Ausführung der dem Taster zugeordneten Aktion schaltet man die PCINTs 
dann wieder ein und legt den Controller wieder schlafen. Bis zum 
nächsten Tastendruck.

Damit hält die Batterie in einer Fernbedienung dann eine kleine 
Ewigkeit.

Ich meine, mal gelesen zu haben, daß Atmel die Pinchange Funktionalität 
genau für sowas eingeführt hat.

von batman (Gast)


Lesenswert?

Hmm naja, etwas unsauber gelöst. Da hätte Atmel ruhig noch ein 
Latchregister für die genaue IRQ-Quelle spendieren können. Wenn man so 
ein batteriebetriebenes AVR-Gerät durch einen kurzen Tastendruck aus dem 
Power-Down einschaltet (was schon einige ms dauern kann), wird dann 
manchmal noch die Tastenfunktion ausgelöst oder auch nicht - je nachdem 
wie lange man drückt.

von Thomas E. (thomase)


Lesenswert?

batman schrieb:
> was schon einige ms dauern kann)

Wie kommst du darauf?

Das dauert ein paar µs. Diese Zeit ist bei Tastendrücken 
vernachlässigbar.

von batman (Gast)


Lesenswert?

So schnell kann das nicht gehen, wenn z.B. ein Quarz-Oszillator 
gestartet werden muß.

Aus dem DB, Power-Down Mode:
The wake-up
period is defined by the same CKSEL Fuses that define the Reset Time-out 
period, as described in ”Clock
Sources” on page 28.

Hier findet man Zeiten bis 65ms.

von Thomas E. (thomase)


Lesenswert?

batman schrieb:
> Hier findet man Zeiten bis 65ms.

Das ist richtig. Aber als Anwendung in diesem Fall nicht sinnvoll.

Prädestinert ist der Betrieb mit internem RC.

von Peter D. (peda)


Lesenswert?

batman schrieb:
> wird dann
> manchmal noch die Tastenfunktion ausgelöst oder auch nicht - je nachdem
> wie lange man drückt.

Nur wenn man es ungeeignet programmiert.
Ist der Puls zu kurz, kann es passieren, daß der Pin im Interrupthandler 
wieder auf dem alten Pegel ist oder auch, daß der Interrupthandler gar 
nicht erst angesprungen wird.
Bei Entprellung im Timerinterrupt führt beides nicht zu einer 
Fehlerkennung der Taste. Der MC wacht einfach nur auf und geht wieder 
schlafen, wenn der Timerinterrupt keine Änderung festgestellt hat.
Ich nehme für das Aufwachen immer einen EMPTY_INTERRUPT, d.h. der 
Interrupthandler besteht nur aus einem RETI.

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.