ich habe folgendes vor, ein Taster an INT0 soll dafür sorgen, dass die onboard LED eine Sekunde leuchtet, solang der Taster gedrückt ist.
Wenn der Timer die Sekunde erreicht hat oder der Taster innerhalb der Sekunde losgelassen wird soll die LED erlöschen.
Sehe ich es richtig das ich demnach 3 verschiedene ISR brauche, eine für Timer match, eine für steigende und eine für die fallende Flanke an INT0?
Vergiss Interrupts und Timer dafür. Taster fragt man sowieso sehr, sehr selten per Interrupt ab, da sie Prellen.
Auf dem Arduino läuft auf Timer0 schon ein Timer, das alle 1ms inkrementiert. Dessen Zählerstand bekommt man mit millis(). Dadurch kann man abfragen wo lange der Arduino läuft. Und wenn man die Differenz aus zwei Zeitstempeln bildet abfragen ob eine bestimmte Zeit vergangen ist.
Taster prellen und der Tastendrücker kann einen Taster nicht so schnell und kurz drücken daß die Verarbeitung zeitkritisch ist bzw de Controller sie übersieht.
Das Prellen macht am Interrupt große Probleme da der Controller das Tastendrücken 3-4 mal sieht.
Die Zeit kannst Du einfach mit millis) machen.
Grüße Uwe
Ich versteh euch und eure Bedenken aber ich möchte es doch verstehen, das war eben ein Beispiel was man gut nachvollziehen kann.
Gehen wir einfach davon aus das der Tester extern entprellt wird.
Diese Timer und Interrupt Geschichte interessiert mich schon lang, ich will das einfach mal verstehen.
Die Tutorials die ich fand fassen solch einen Fall leider nicht auf.
Wenn du Timer verstehen willst, nimm ein anderes, einfacheres Beispiel. z.B. eine LED regelmäßig blinken lassen. Das geht sowohl mit als auch ohne Interrupts.
Oder wenn du was anspruchsvolles willst, PWM per Hand implementieren
Die Tutorials decken das nicht ab, weil es eine unsinnige Anwendung für Interrupts und Timer ist. Nicht nur wegen dem Taster.
das Bsp. zu programmieren ist übelst kompliziert von hinten durch Auge und noch mehr.
Und leider so auch nicht programmierbar. Der Taster hängt ja an einem Pin der immer gleich ist. Wenn man den an einen Timer Eingang anschließt und guckt auf die Flanken, dann ist genau das hier das Problem. Man kann den Timereingang nur auf entwederrising edgeoderfalling edge einstellen. Du müßtest wenn dann die Zeit nehmen zwischen 2 gleichen Flanken.
Du müßtest irgendwie im CTC Mode dir die Zählerstände merken und vergleichen und dergleichen und zwischen den Interrupts Compares springen. Das macht so wirklich niemand. Selbst wenn man das irgendwie hinbekommt, würde man das später in der Form nie verwenden.
Ich möchte dir das nicht ausreden, nur müßtest du den Timer und seine Möglichkeiten erstmal grundlegend verstanden haben. Damit solltest du dich zuerst befassen. Wie man die verschiedenen Modi einstellt, wie man an den Pins eines Ports mittels Timer alle Pins takten läßt usw. Da gibt es viel zu entdecken. Der CTC Mode ist zum Bsp. sehr vielseitig. Und statt auf Taster zu warten kannste dir einen Frequenzzähler programmieren usw. Das µC Datenblatt mußte dazu jedoch zwingend zur Hand nehmen.
ich habe folgendes vor, ein Taster an INT0 soll dafür sorgen, dass die onboard LED eine Sekunde leuchtet, solang der Taster gedrückt ist.
Diese Anforderung ist nicht erfüllbar, weil wiedersprüchlich.
Die Tastenerkennung könnte man mit Interrupts machen, ist aber eher unhandlich und sicherlich unnötig.
Eine Led eine Sekunde leuchten zu lassen, würde ich mit millis() machen, also keinen Timer benutzen.
in der ISR dazu dann INT0 deaktivieren und als INT0 falling wieder aktivieren
LED auf high
Timer1 starten
in die ISR für INT0 falling und in der ISR für Timer1 match kommt das selbe:
INT0 deaktivieren und wieder auf INT0 rising setzen
LED auf low
Timer1 zurücksetzen
Damit springt er so hoffe ich eben durch die IRS´s
Oder lieg ich da völlig daneben?
Nur würde ich nicht alles in die ISR packen sondern status Variablen in der ISR umschalten und diese in der loop auswerten und von dort aus die LED schalten.
Taster INT0 mit rising erkannt gibt status LED on
INT0 auf falling ändern
aus INT0 ISR heraus wird Timer 1 gestartet, sein ISR eingestellt auf 1sec
....
INT0 ändert status Variable LED off wenn Taster losgelassen
ISR Timer 1 ändert seine status Variable wenn sein compare auslöst.
Beide status Variablen wertest du in der loop aus und setzt die Timer zurück oder stoppst sie o.ä.
Unnötig kompliziert und mit den dauerenden Wechseln in der ISR eher unzuverlässig.
Nimm CHANGE als Interrupt und werte in der ISR den Tastenzustand aus.
Dann musst du noch die Taste entprellen (auch wieder mit Interrupts unnötig kompliziert).
Aber es geht ja wohl eh darum, etwas möglichst kompliziert zu machen.
Nunja in 99,9% der Zeit macht der Arduino ja garnichts also kann man nichtmal von "ständigem Wechsel" der ISR´s reden, zuverlässig sollte es sein wenn ich keinen Fehler mache.
Mich würde mal interessieren ob ich, wenn INT0 auf rising gesetzt ist, ihn einfach ändern kann auf falling oder ob ich ihn dazu erst ausschalten muß, was ich so gefunden habe geht es wohl ohne extra auszuschalten.
Kann das jemand bestätigen?
er möchte was eigentlich sinnloses probieren. Es geht ihm um die Timer ISRs. Warum nicht, soll mal machen.
Solange er das später nicht immer so macht ...
Ausschalten mußte nichts. Einfach umschalten. Wenn du ganz sicher gehen möchtest, schaltest du vorher alle Interrupts aus und nach der Änderung wieder ein. cli(); bzw. sei(); Dann kann während dieser Zeit nichts dazwischen funken.
Pool13:
Mich würde mal interessieren ob ich, wenn INT0 auf rising gesetzt ist, ihn einfach ändern kann auf falling oder ob ich ihn dazu erst ausschalten muß, was ich so gefunden habe geht es wohl ohne extra auszuschalten.
Kommt drauf an
Du mußt dafür sorgen, daß kein unerwünschter Interrupt auftritt, weil das Interrupt-Flag vor oder nach dem Umschalten noch oder schon wieder gesetzt ist. Im ISR kann man davon ausgehen, daß das Flag beim Aufruf automatsch gelöscht wird, und die andere Flanke noch nicht durch ist, also wäre garnichts zu tun.
Interrupts sind beim Aufruf einer ISR automatisch gesperrt, und werden beim Verlassen wieder eingeschaltet. Damit wird vermieden, daß sich Interrupts gegenseitig unterbrechen.
In speziellen Fällen kann es besser sein, die Interrupt-Enable Flags für die jeweilige Quelle umzuschalten, als alle Interrupts gemeinsam. Die sei() und cli() würde ich garnicht verwenden, da ich mir die Unterschiede nicht merken kann, die bei unterschiedlichen Prozessoren existieren. In loop() kann man interrupts() und noInterrupts() verwenden, die sind eindeutig benannt und machen auch nichts anderes. Ansonsten sollte man vor dem Ausschalten aller Interrupts den vorherigen Zustand speichern und hinterher restaurieren, damit nicht versehentlich Interrupts wieder erlaubt werden, die zuvor in einem anderen Unterprogramm schon abgeschaltet wurden!
das möchte ich korrigieren. Globaler Interrupt aus/ein ändert keine Feineinstellung irgendwelcher anderer Interrupts. Das heißt nur das Interrupts ab jetzt generell erlaubt oder nicht erlaubt sind.