also global?
dann ist es automatisch "static" und "volatile" brauchst du dann überhaupt nicht.
- - - Aktualisiert - - -
edit - Frage hat sich erübrigt
- dann allerdings verstehe ich deinen Code nicht, da muss jemand anderes 'ran![]()
also global?
dann ist es automatisch "static" und "volatile" brauchst du dann überhaupt nicht.
- - - Aktualisiert - - -
edit - Frage hat sich erübrigt
- dann allerdings verstehe ich deinen Code nicht, da muss jemand anderes 'ran![]()
Derzeit wird nach Pin-Interrupt, innerhalb der ISR-Funktion "ISR_Taste1()" eine Tastenentprellungs-Funktion "Entprell(Pin)" aufgerufen.
Dauert ca.30ms.
Eine Var. mit 1 für Entprellt oder 0 für Fehlerhaft kommt zurück.
Die "ISR_Uebergabe" wird innerhalb des void loop() verändert
Ich Frage mich, ob ich der ISR-Routine nicht zu viel zu mute.Code:void ISR_Taster1() { // Funktion wirdausggeführt, sobald ISR auslöst if(Entprell(TasterPin1 == 1) { if (ISR_Uebergabe == 1) { SummerTon(); } if (ISR_Uebergabe == 2) { SummerTon(); Pausen_ms(100); SummerTon(); } if (ISR_Uebergabe == 3) { SummerTon(); Pausen_ms(100); SummerTon(); Pausen_ms(100); SummerTon(); } } }
__________________________________________________ _
| Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |
Mach das nicht.
Das geht ganz schnell schief.
Nimm dir irgendeine Variable, die innerhalb der ISR geändert wird- nichts weiter.
Alles andere (z.B. die Variable auswerten, dass sie erst ab dem 30. Mal zählt (Entprellung für Arme, einfach, reicht aber oft) mach ausserhalb.
Wenn du sicher gehen wllst, dann mach in der ISR folgendes:
-Interrupts deaktivieren
-tun, was zu tun ist
-Interrupts aktivieren
So stellst du sicher, dass innerhalb der ISR kein Interrupt ausgelöst wird- das nämlich ist das Problem mit ISR's.
Wenn dir sowas passiert, wird die ISR aufgerufen, während sie noch läuft...du kannst dir denken, wie _das_ endet.
Grüssle, Sly
..dem Inschenör ist nix zu schwör..
genau, und Variable, die innerhab einer ISR geändert werden, sollten wieder global deklariert werden und volatile sein.Nimm dir irgendeine Variable, die innerhalb der ISR geändert wird- nichts weiter.
Alles andere (z.B. die Variable auswerten, dass sie erst ab dem 30. Mal zählt (Entprellung für Arme, einfach, reicht aber oft) mach ausserhalb.
Geändert von HaWe (22.11.2019 um 12:05 Uhr)
Vorsicht, das geht in die Hose.
Von vorne mal angefangen. Das Deaktivieren des Interrupts am Anfang ist nicht das erste, was im Interrupthandler passiert. Da laufen noch ein Dutzend oder mehr Assemblerbefehle vorher ab, wie Status und Register retten. Wenn dort der Interrupt nicht automatisch gesperrt wäre, würde der Interrupt sofort wieder zuschlagen, da das Interruptflag noch nicht gelöscht ist. Der Interrupt muß also noch vor dem ersten Assemblerbefehl gesperrt werde, und das geht nur, wenn es automatisch passiert. Und so ist es auch. Beim Eintritt in den Interrupthandler ist mindestens dieser interrupt gesperrt. Den Interrupt im Handler zu deaktivieren ist zwar nicht unbedingt schädlich aber überflüssig und käme auch viel zu spät.
Das Aktivieren ist aber schlecht. Zwischen dem letzten C-Befehl und dem Ende der Funktion wird das, was am Anfang des Handlers gesichert wurde, wiederhergestellt. Das sind nochmal ein Dutzend oder mehr Befehle. Die laufen jetzt mit offenen Interrupts und das ist gefährlich. Erst ganz am Ende, wenn der Prozessor den Interruptkontext verlassen hat, dürfen die Interrupte wieder zugelassen werden. Daher endet ein Interrupthandler auch nicht mit einem Return (from Subroutine) sondern einem Return from Interrupt. Das heißt häufig RETI. Der stellt den Interrupstatus wieder so ein, wie er vor dem Interrupt war.
MfG Klebwax
Geändert von Klebwax (23.11.2019 um 19:42 Uhr)
Strom fließt auch durch krumme Drähte !
Kann sein, aber wie macht man´s besser?
Zwischen
attachInterrupt(Taster01Pin, ISR_Taster1, RISING);
und
ist nicht mehr viel Platz.Code:ISR_Taster1() { noInterrupts(); // alle Interrupts ausschalten Variable = Entprellung(); // volatile, ~30ms interrupts(); // alle Interrupts wieder einschalten }
__________________________________________________ _
| Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |
erst mal evt das hier wieder streichen (ich kann es nicht beurteilen, was nun stimmt, Klebwax vs. Rabenauge):
noInterrupts(); // alle Interrupts ausschalten
interrupts(); // alle Interrupts wieder einschalten
ich vermute, 30ms warten ist auch etwas lang für eine ISR, und wenn das so ist: dann eine Statemachine programmieren:
erst state1=0,
beim 1.Tastendruck per Interrupt: state1=1 und timestamp1=millis()
dann millis()-timestamp1 in loop() kontrollieren und sobald 30ms erreicht ist: Tastendruck verarbeiten und state1 wieder auf 0.
Ich mache das bisher ganz ohne Interrupts in einer C++ Klasse, auch zum Erkennen und Unterscheiden von kurzem Click, langem Press und Doppelklick.
Aber ich weiß ntl nicht, ob dich meine Lösung interessiert, sonst zeige ich sie dir gerne...
Natürlich interessiert mich das - kann ja durch andere (erfahrene) Gedanken nicht blöder werden
Ich finde die ISR-Auslösungen schon super - mit einer state-Mashine kombiniert - und dann als universelle Standart-Funktion mit der ich mich nie wieder beschäftigen muss... !
Daher war mein Ursprungsgedanke, dass der Interrupt ein Sprungziel in die loop()-Funktion defeniert - mehr nicht.
Dort wird dann erneut die Tastenabfrage/Entprellung und alles folgende vor genommen.
Geht das überhaupt?
__________________________________________________ _
| Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |
Lesezeichen