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
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?
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
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.
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.
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.
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
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 ...
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.
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.
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.
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.
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.
Peter D. schrieb:> 90µs sind bei 8MHz Takt 720 CPU-Zyklen, da besteht keine Gefahr, daß der> MC zu langsam ist.
Da wäre ich vorsichtig, wegen:
Sidey schrieb:> (ich nutze die Arduino Funktionen um den pin abzufragen)
Interessant wäre natürlich, woher das Signal kommt und was Du damit
machen willst.
Je genauer man eine Aufgabe beschreibt, umso einfacher läßt sie sich
implementieren.
Wenn man aber nur wenig preisgibt, wird die Lösung oft nur unnötig
kompliziert.