Hallo zusammen, ich hätte noch mal eine Frage: Ich habe nun drei verschiedene Lauflichter, die ich in Unterprogramme gegossen habe. Jeder Aufruf des UP ist EIN Lauflichtdurchlauf. D.h. im Kernprogramm muss in einer Schleife ständig mein Lauflichtunterprogramm aufgerufen werden. Nun würde ich gerne folgendes realisieren: Wenn ich eine bestimmte Taste drücke, (aber nicht gedrückt halte) soll ab diesem Zeitpunkt das erste Lauflicht in einer Loop aufgerufen werden, wenn ich dann die gleiche Taste nocheinmal kurz drücke, soll das andere Lauflichtprozedur in der Loop aufgerufen werden und das gleiche beim dritten Lauflicht. Beim vierten Tastendruck sollte wieder das erste Lauflicht in der Loop aufgerufen werden. So könnte ich durch Tastendrücke durch die einzelnen Programme durchsteppen. Ich nehme an, man braucht einen kleinen Zähler, der beim drücken der Taste hochgezählt wird, ab drei dann wieder auf Null gesetzt wird usw. Und in der Loop wird je nach Zählerstand die eine oder andere Prozedur angesprungen. Aber wie kann ich dieses durchsteppen realisieren? Möglichst ohne Interrupts, weil ich da noch gar nicht durchblicke. Vielen Dank Karl
"Möglichst ohne Interrupts, weil ich da noch gar nicht durchblicke." Dann ist das doch ein guter Zeitpunkt, damit anzufangen. Die externen Interrupts braucht man eher selten, aber die Timerinterrupts sind unverzichtbar, will man in seinem Programmablauf den Überblick behalten. In Deinem Fall brauchst Du ihn, um die Tasten zu entprellen und das hintereinander Drücken zu erkennen. Der Rest Deiner Aufgabe ist eine Statemaschine, z.B. Du hast eine Variable, die die verschiedenen Zustände kennzeichnet und je nach Zustand auf einen anderen Wert (=Zustand) wechseln kann. Am elegantesten könnte man beides mit meinem Sheduler-Beispiel machen, aber da sollte man schon etwas Erfahrung mit den Timern und mit C haben. Peter
Hi... Du wirst um den Timer-Interrupt nicht herum kommen... Ansonsten wird das viel zu kompliziert. Versuchs zuerst mit dem Timer0-Overflow, da ist das Wenigste zu beachten. Stell den so ein, dass der alle paarhundert Takte ausgelöst wird (erster Versuch: (Vorteiler)64 mal (Zählumfang)256). Wenn du mit dem klar kommst, wirst du sehen, dass ein Programm mit Interrupts viel einfacher wird als diese "WaitXYZ"-Aufrufe. Außerdem schafft der Timer-Int die Basis dafür, mehrere verschiedene Programmteile (scheinbar) gleichzeitig abzuarbeiten. Hängst du bei einem Programm mit Wait-Aufrufen in der Warteschleife, dann kannst du nix Anderes machen, der Prozessor ist mit der Warteschleife voll ausgelastet. Vergiss also diese Programmiermethode... (möglichst schnell) Deine Taste braucht übrigens neben dem Zähler noch eine Entprellung. Der Externe Interrupt ist dazu denkbar ungeeignet, der würde bei einem (mechanisch erzeugten) Tastendruck etliche male aufgerufen. Geh also andersrum an das Programm ran: - Bau kein Programm, in das du zum Verzögern Zeitschleifen aufrufst, - Bau einen Zeittakt (Timer-Int), in dem du Programm abarbeitest... Dazu ist das "ganz spezielle Lauflicht" allerdings denkbar ungeeignet... Grundlagen zum Timer-Int findest du im oben erwähnten Blink-Programm. Fang klein an: - Int-Vektoren zu Programmbeginn anlegen (siehe Datenblatt oder Include-Datei ganz unten), - Reset-Routine schreiben, in der Folgendes gemacht wird: - Stackpointer initialisieren, - Ports initialisieren, - Timer0 am Prozessortakt 1:64, (3 in tccr0 schreiben, Datenblatt Seite 70) - Timer0-Overflow aktivieren, (toie0 in timsk setzen, DB S.70) - mit SEI Interrupts freischalten, - Ein Hauptprogramm (Schleife) schreiben, in dem (vorerst) nix gemacht wird: main: rjmp main Später kommt da noch Programm dazu, ist das fertig, dann schickt es den AVR schlafen... - eine ISR (Interrupt-Service-Routine) schreiben, dort musst du: - SREG sichern, - (später mal) Timer-Reload-Wert in tcnt0 schreiben, - (später mal) ein Register hochzählen, welches vom Hauptprogramm als "Stopuhr" genutzt werden kann (akt. Wert merken, Wartezeit addieren, warten bis zum Gleichstand, geht auch mit zwei Registern (16 Bit) für längere Wartezeiten), - den Code meiner Hauptschleife (außer Warteschleife, denn das macht jetzt der Timer, indem er den Programmteil periodisch aufruft) einfügen (ohne Rücksprung am Ende zum Codebeginn), - später mal weiteren Code einfügen, z.B. Tastenabfrage, aber bitte nix mit Verzögerung! (Weitere Tricks folgen später, die würden dich jetzt nur unnötig verwirren), - SREG wiederherstellen, - die ISR mit RETI abschließen. Du musst allerdings darauf achten, dass zwischen den einzelnen Aufrufen des Timer-Int genügend Zeit zur Abarbeitung der ISR bleibt (und auch noch für das spätere Hauptprogramm!). Aber dabei ist der Simulator des AVR-Studios dein Freund... Wenn das alles läuft, kannst du ja mal darüber nachdenken, wie man andere (ganz besondere?) Lauflichter so umstrukturiert, dass sie bei periodischem Aufruf des Programmteils funktionieren. Die Denkweise ist also völlig anders: Der Timer-Interrupt gibt dir einen (recht genauen, zumindest von der Länge der ISR unabhängigen) Takt vor, in dem der Programmteil, den man sonst in einer Schleife (mit "Bremse") abarbeiten würde, zyklisch aufgerufen wird. Brauchst du "Bremsen", so musst du halt die ISR-Aufrufe zählen und deinen Programmteil überspringen, falls eine Wartepause aktiv ist. Viel Erfolg... ...HanneS...
Ups... @Peter: Das kommt davon, wenn man abgelenkt wird (Insulin-Spritzzeit, essen) und daher über eine Stunde zum Schreiben des Beitrags braucht... ;-) ...HanneS...
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.