Erkennen, was den Interrupt ausgelöst hat.

Gast #4324967
Lesenswert?
• ▲
▼
Hallo,

ich verwende einen Interrupt (INT_EXT_0) eines Arduino Nano.
Der hat einen ATMega 328.

Der Interrupt soll bei steigender und fallender Flanke auslösen.
Das klappt auch wunderbar.

Im ISR, benötige ich jedoch den Grund er Auslösung.
Ich frage bisher den Status vom Port ab, allerdings kann ich mir 
vorstellen, dass in einem Register hinterlegt ist, was den Interrupt 
ausgelöst hat. Also ob eine steigend oder fallende Flanke.

Im Datenblatt habe ich zum EXT_INT0 aber nichts gefunden und im Forum 
hier leider auch nicht.
Gibt es so ein Register?

Grüße Sidey
Gast #4325096
Lesenswert?
• ▲
▼
Das Datenblatt gibt da nichts her..

Ich würde mal behaupten, dass es (so) nicht  geht.
Du hast momentan die einstellung auf 01, any logical change?
Dann kriegst du natürlich einen Interrupt bei jedem logical change..

Wenn dich wirklich die Art der Flanke interessiert, könntest du 
natürlich beide ExtInts mit der Quelle verbinden, einen auf rising, 
einen auf falling, und schon hast du die klare unterscheidung?
Gast #4325104
Lesenswert?
• ▲
▼
Walter S. schrieb:
> Mobi schrieb:
>>> Wozu sollte es noch ein anderes Register geben...
>> Weil sicher der Status des Portpins zwischzeitlich geaendert haben kann.
>
> dann fragt man bzw. merkt sich den Zustand vorher, dann weiß man welche
> Flanke es gewesen sein muss

Blödsinn.

Man muss eben das Interruptflag auswerten. Für Arduino Menschen geht das 
wie hier im Beispiel https://www.arduino.cc/en/Reference/attachInterrupt 
in der Funktion blink(). Diese ist die ISR für den gewählten Interrupt 
(CHANGE im Beispiel). Das ist genau was du brauchst.
Gast #4325107
Lesenswert?
• ▲
▼
Falls du wissen möchtest ob steigende oder fallende Flanke:
Zwei ISRs wie im oberen Beispiel. In der jeweiligen ISR änderst du eine 
Variable auf 1 oder 2 je nach Typ (fallend, steigen). In der loop() 
frägst du immer ab ob sie 0, 1 oder 2 ist. Wenn 1 oder der 2 entstanden 
rechend was passieren soll bei fallend oder steigend. Wenn du damit 
fertig bist, setzt du sie auf 0.
Gast #4325116
Lesenswert?
• ▲
▼
1
volatile char c_InterrType = 0;
2

3
void setup() {
4
    attachInterrupt(digitalPinToInterrupt(pin), risingISR, RISING);
5
    attachInterrupt(digitalPinToInterrupt(pin), fallingISR, FALLING);
6
}
7

8
void loop() {
9
    if(c_InterrType > 0){
10
     Switch(c_InterrType){
11
      Case 1: //irgendwas bei falling 
12
       Break;
13
      Case 2: //irgendwas bei rising 
14
       Break;
15
      }
16
    }
17
}
18

19
void fallingISR() {
20
    c_InterrType = 1;
21
}
22

23
void risingISR() {
24
    c_InterrType = 2;
25
}
#4325133
Lesenswert?
• ▲
▼
123 schrieb:
> Walter S. schrieb:
>> Mobi schrieb:
>>>> Wozu sollte es noch ein anderes Register geben...
>>> Weil sicher der Status des Portpins zwischzeitlich geaendert haben kann.
>>
>> dann fragt man bzw. merkt sich den Zustand vorher, dann weiß man welche
>> Flanke es gewesen sein muss
>
> Blödsinn.

Und das löst auf einem Mega328 das Problem wie genau?

Ist ja schön, dass das Arduino Framework die Portpin Auswertung für dich 
macht. Aber zaubern kann die auch nicht. Was der µC nicht hergibt, das 
gibt er nicht her. In diesem Fall eine Möglichkeit (ausser den Portpin 
abzufragen), welche Flanke es war.
#4325135
Lesenswert?
• ▲
▼
123 schrieb:
> Blödsinn.
>
> Man muss eben das Interruptflag auswerten. Für Arduino Menschen geht das
> wie hier im Beispiel https://www.arduino.cc/en/Reference/attachInterrupt
> in der Funktion blink(). Diese ist die ISR für den gewählten Interrupt
> (CHANGE im Beispiel). Das ist genau was du brauchst.

123 schrieb:
> attachInterrupt(digitalPinToInterrupt(pin), risingISR, RISING);
>     attachInterrupt(digitalPinToInterrupt(pin), fallingISR, FALLING);

toll was der Arduino alles kann ...
falls du da wirklich beide Flanken getrennt zuordnen kannst dann schau 
doch bitte mal nach wie das in der Bibliothek gemacht wird, würde mich 
interessieren
Gast #4325139
Lesenswert?
• ▲
▼
123 schrieb:
> attachInterrupt(digitalPinToInterrupt(pin), risingISR, RISING);
> attachInterrupt(digitalPinToInterrupt(pin), fallingISR, FALLING);

Schreiben kann man das - aktivieren wird man damit aber nur den 
Interrupt für die fallende Flanke (die letzte Einstellung zieht). Pro 
Pin kann man nur entweder oder bzw. generell Flankenwechsel einstellen. 
Kann man sogar im Datenblatt nachlesen.

Wenn der Flankenwechsel (deutlich) langsamer ist wie der ISR-Prolog + 
Abfrage des Port-Zustandes, dann kannst Du ja aus dem aktuellen Zustand 
in der ISR (bei Einstellung Interrupt bei jedem Flankenwechsel) auf den 
Flankenwechsel schließen. Wenn der Flankenwechsel schneller ist wie die 
Dauer der ISR insgesamt hast Du sowieso ein Problem ...
Gast #4328751
Lesenswert?
• ▲
▼
Vielen Dank für die vielen Antworten.

Also, Flankenwechsel die unter 90 Mikrosekunden Abstand haben, sind für 
mich ohnehin nur Müll, wenn öfter welche reinkommen wird das bei mir 
ohnehin gefiltert.

Aktuell habe ich es wie empfohlen so gelöst, dass ich nach dem Auslösen 
des ISR den Pin Status abfrage und daraus schließe ob der port jetzt 
high oder low ist, was der Zustand zuvor war.

Allerdings bin ich mir nicht so sicher, ob der Zustand dauerhaft richtig 
erkannt wird. Ich hatte so einen Verdacht, dass das Abfragen des Port 
Zustandes vielleicht etwas langsam sein könnte und der ISR dann ggf. 
zwischenzeitlich noch mal auslöst.

(ich nutze die Arduino Funktionen um den pin abzufragen)

Das invertieren von State bei jedem ISR könnte ich auch machen.
Initial müsste ich dann nur den richtigen Zustand einmal abfragen (geht 
je vor Aktivieren des ISR) und anschließend hoffen, dass der ISR nicht 
öfter auslöst, als ich die Variable negieren kann.

Die Variante mit dem 2. ISR geht, aber den möchte ich ggf. noch mal für 
was anderes verwenden. Alternativ könnte ich ja auch jedes mal wenn der 
ISR ausgelöst wird, den trigger anpassen.
Gast #4328917
Lesenswert?
• ▲
▼
Sidey schrieb:
> Ich hatte so einen Verdacht, dass das Abfragen des Port
> Zustandes vielleicht etwas langsam sein könnte und der ISR dann ggf.
> zwischenzeitlich noch mal auslöst.

Das passiert nur wenn du das explizit erlaubst.
Also eine unnütze Angst.

Sidey schrieb:
> (ich nutze die Arduino Funktionen um den pin abzufragen)
Das kannst du ändern.
#4329018
Lesenswert?
• ▲
▼
Karl H. schrieb:
> Was der µC nicht hergibt, das
> gibt er nicht her. In diesem Fall eine Möglichkeit (ausser den Portpin
> abzufragen), welche Flanke es war.

Ein Atmega8 gibt das natürlich nicht her. Aber ein 328er...

Wenn man den INT0 Sense auf Falling Edge stellt und diesen NICHT 
enabled, stattdessen aber den entsprechenden Pin-Change einschaltet, 
kann man durch Auswertung des INTF0 und ggf. des PCIF0 erkennen, ob der 
Pin-Change mit steigender oder fallender Flanke ausgelöst hat.

Wird er mit steigender Flanke ausgelöst, ist das INTF0 nicht gesetzt und 
die Abfrage des Flags ist eindeutig.

Wird mit fallender Flanke ausgelöst, ist INTF0 gesetzt, aber die Abfrage 
nicht eindeutig. Denn es könnte zwischen dem Auslösen des PCINT mit 
steigender Flanke und der Abfrage des INTF0 ein weiterer Flankenwechsel 
stattgefunden haben, der erst dann das INTF0 setzt. In diesem Fall ist 
aber auch das PCIF0 erneut gesetzt.

Somit kann aus einer Kombination der Abfrage beider Flags eindeutig 
bestimmt werden, welche Flanke den Interrupt zuerst ausgelöst hat und in 
welchem Status er sich bei der Abfrage befindet.

PCIF0 | INTF0 = 0 >> Rising Edge
PCIF0 | !INTF0 = 0 >> Falling Edge
PCIF0 & INTF0 = 1 >> Rising Edge, aber noch vor der Abfrage
                                 Wechsel auf Falling Edge

mfg.
#4329035
Lesenswert?
• ▲
▼
Thomas E. schrieb:
> PCIF0 & INTF0 = 1 >> Rising Edge, aber noch vor der Abfrage
>                                  Wechsel auf Falling Edge

Autsch:

Dieser Zustand ergibt sich auch bei Falling Edge und nachfolgendem 
Wechsel auf Rising. Hier muß zusätzlich die Portabfrage herhalten:

PCIF0 & INTF0 & !PIND2 = 1 >> Rising Edge, aber noch vor der Abfrage
                                           Wechsel auf Falling Edge


PCIF0 & INTF0 & PIND2 = 1 >> Falling Edge, aber noch vor der Abfrage
                                            Wechsel auf Rising Edge

mfg.
#4329140
Lesenswert?
• ▲
▼
Sidey schrieb:
> Also, Flankenwechsel die unter 90 Mikrosekunden Abstand haben, sind für
> mich ohnehin nur Müll,

Sidey schrieb:
> Allerdings bin ich mir nicht so sicher, ob der Zustand dauerhaft richtig
> erkannt wird.

90µs sind bei 8MHz Takt 720 CPU-Zyklen, da besteht keine Gefahr, daß der 
MC zu langsam ist.
Hauptsache Du verwendest keine Delays im Interrupthandler.
Oder LCD-, UART-Ausgaben, Float, Division und anderes lahmes Zeugs.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.