Forum: Mikrocontroller und Digitale Elektronik Tim. Inter. soll Buchstaben im Wechsel anzeigen


von Mirko Kamm (Gast)


Lesenswert?

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

von Reiner (Gast)


Lesenswert?

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

von Hannes L. (hannes)


Lesenswert?

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.

...

von Mirko Kamm (Gast)


Lesenswert?

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

von Hannes L. (hannes)


Lesenswert?

> 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.

...

von peter dannegger (Gast)


Lesenswert?

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

von Mirko Kamm (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.