Hallo, ich versuche ein einfaches Programm zu schreiben mit dem Ziel, dass im 3 Sekunden Abstand jeweils ein "F" und ein "K" angezeigt werden soll. Eigentlich recht simpel. LCD Anzeige: "F" 3 Sekunden warten LCD Anzeige: "K" 3 Sekunden warten LCD Anzeige: "F" usw..... Zum Timerverständnis habe ich schon LEDs in 1 Sekunden Takt blinken lassen, realisiert mit einem Timer Overflow bzw. auch mit einem TimerCompare Match. Mein Problem: Wie schaffe ich es, das Programm so zu gestalten, dass in der Timer Interrupt Routine erkannt wird, welcher Buchstabe gerade angezeigt wird? Ich will keine Code Beispiele, sondern ein Tip. Ich habe mal gehört, dass in einer Interrupt-Routine selbst so wenig Aktion wie möglich sein sollte. Prozessor: AVR Sprache: Assembler Software: AVR Studio Danke für eure Tips. MFG Mirko
Hallo Mirko, Im Timerinterrupt einfach ein bit togglen ( 0-1-0-1...) Ausserhalb des Interrupthandlers: Wenn bit gesetzt: LCD Anzeige "F" ansonsten LCD Anzeige "K" Der Interrupthandler braucht ja nicht zu wissen welcher Buchstabe gerade angezeigt wird. Er soll den Takt liefern. Reiner
Also ich organisiere inzwischen alle meine Programme so, dass sie durch einen Timer synchronisiert werden. Das heißt, dass die Mainloop mit all ihren Unterprogrammen nach getaner Arbeit in den Sleep fällt und "die nächste Runde" erst nach einem weiteren Interrupt (meist Timer) absolviert. Wenn auch andere Interrupts genutzt werden, dann setzt der Timer-Interrupt ein Flag, das von der Mainloop zur Verzweigung genutzt wird. Somit wird der "getaktete Teil" der Mainloop im genau definierten Zeitraster aufgerufen und kann auch Zeitmessaufgaben übernehmen. Soll nun, wie in deinem Fall, in einem definierten Zeitabstand eine Aktion stattfinden, so nimmt man eine Variable (Register, Hilfsregister und SRAM-Zelle) als Software-Timer, indem man sie (in jeder "Runde") hoch bzw. runter zählt und bei Erreichen des Zählumfangs wieder auf Startwert setzt und die Aktion auslöst. Sollen wechselweise verschiedene Werte ausgegeben werden, dann muss man sich den zuletzt ausgegebenen Wert merken und danach beim nächsten mal bestimmen, welcher Wert jetzt an der Reihe ist. Da LCDs meist im WriteOnly-Mode betrieben werden, ist ein Zurücklesen des zuletzt geschriebenen Zeichens meist nicht möglich. Also muss man sich das Zeichen in einer Variablen (Register oder SRAM) merken. Wenn das Zeichen immer an die selbe Stelle des LCDs soll, dann muss die Ausgabeposition des LCDs auch jedesmal neu gesetzt werden. Du wolltest zwar keinen fertigen Code, darfst aber gerne mal bei www.hanneslux.de/avr/ nachschaun, wie ich das gemeint habe. In den Projekten Stoppuhr und Zünduhr dürftest du fündig werden. ...
Hallo, dass bedeutet also, dass wenn ich eine sich im 3 Sekunden Abstand ändernde reele Zahl anzeigen lassen will (Temperatur), dann muss ich mir mal Deine Routine anschauen Hannes. MFG Mirko
> dass bedeutet also, dass wenn ich eine sich im 3 Sekunden Abstand > ändernde reele Zahl anzeigen lassen will (Temperatur), > dann muss ich mir mal Deine Routine anschauen Hannes. Neee... - Denn da wird keine Temperatur alle 3 Sekunden angezeigt 8D Aber da werden laufende Zeiten und andere Informationen im festgelegten Zeitraster angezeigt, woran du nachvollziehen kannst, was ich mit meiner Beschreibung meinte. Es geht dabei mehr um das Grundkonzept eines Programms als nur um die Anzeige im bestimmten Zeitraster. Wenn nämlich dieses Grundkonzept schon eine solide Zeitbassis zur Verfügung stellt, braucht man nicht für jede zeitabhängige Aktion einen eigenen Timer oder sogar eine Warteschleife, sondern man ruft diesen Programmteil eben in einem gröberem Zeitraster auf. Dabei lässt man diesen Teil "links liegen" wenn er in der aktuellen "Mainloop-Runde" nicht an der Reihe ist. Die Steuerung, wann jeder Teil an der Reihe ist, wird von einfachen Variablen übernommen, Z.B. BOOLschen Variablen (Flags in einem Register, Tastenflags der Entprellroutine) oder Zählregister. Somit wird an keiner Stelle im Programm gewartet (Warteschleife), sondern der betreffende Teil einfach übersprungen. Dies spart Rechenzeit, die man am Ende der Mainloop durch Sleep wieder "entsorgen" kann... ;-) Spaß beiseite, durch das Vermeiden von Wartezeiten erreicht man eine dermaßen schnelle Abarbeitung der einzelnen Programmteile, dass der Eindruck entsteht, der Controller würde im Multitasking-Betrieb arbeiten. Da dies durch LCD-Routinen mit Warteschleife ausgehebelt werden würde, habe ich die LCD-Ausgabe inzwischen auf Ringbuffer-Betrieb umgestellt. Das eigentliche Programm schreibt die Ausgabetexte und die Positionierung einfach nur in den Ringbuffer. Ein Timer-Interrupt setzt dann alle etwa 1ms ein Flag, worauf die Mainloop die Ausgabe eines Zeichens aus dem Buffer veranlasst. Im Stopuhr-Projekt übernimmt die LCD-Routine sogar die Ausgabe auf UART, was die gesamte Ausgabeprogrammierung total vereinfacht. (Jedes Locate-Macro schaltet auf LCD um, jedes Schreiben einer $01 schaltet auf UART um, womit alle Print-Macros wahlweise auf LCD oder UART wirken können.) Schau es dir ruhig mal an, denn mit diesem Programmierkonzept werden viele Probleme leichter lösbar. Schau auch mal unter Beispielprogramme, da wird das Grundkonzept an einem sehr kleinen Programm für ATtiny15 erläutert. ...
Wenn eine Funktion bei jedem Durchluaf verschiedene Sachen machen soll, setzt man einen Zähler (Variable) auf, erhöht ihn bei jedem Durchlauf und entscheidet daran, was als nächste zu tun ist. Solls wieder von vorne anfangen, setzt man sie auf 0. Bei der Ausgabe verschiedener Zeichen ist dieser Zähler z.B. der Index in einem String:
1 | unsigned char zaehler; |
2 | unsigned char text[] = "FK"; |
3 | |
4 | void print_next( void ) |
5 | {
|
6 | if( text[zaehler] == 0 ) // == 0 ? |
7 | zaehler = 0; // von vorne |
8 | printchar( text[zaehler] ); // Zeichen ausgeben |
9 | zaehler++; // weiterzaehlen |
10 | }
|
Peter
Hallo Jungs, vielen Dank für eure Hilfe, werde mich heute abend mit diesen Infomationen auseinandersetzen. MFG Mirko
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.