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
Wozu sollte es noch ein anderes Register geben, wenn man auch einfach den Portpin abfragen kann?
STK500-Besitzer schrieb: > Wozu sollte es noch ein anderes Register geben... Weil sicher der Status des Portpins zwischzeitlich geaendert haben kann.
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.
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 | }
|
Oh ich hab was vergessen: In der loop() Nach dem Switch{} aber noch innerhalb dem if{} fehlt:
1 | c_InterrType = 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.
Und hardwaremäßig ein Flip Flop vor den INT setzen, das dann über einen Port resetiert wird?
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.
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.