Forum: Mikrocontroller und Digitale Elektronik HD44780 - per Interrupt beschreiben oder immer nach Bedarf?


von Denis (Gast)


Lesenswert?

Hi Leute!

Ich nehme hier gerade in 4x20 HD44780 in Betrieb. Klappt auch alles, 
also keine Frage zur Ansteuerung an sich, sondern eher über die 
geschickteste Variante, die Daten hin zu transferieren.

Ich arbeite mit dem Busy-Flag, also ohne Delays. Obwohl das Busy-Flag 
natürlich auch einem Delay gleichkommt, da ich ja warten muss, bis das 
Display fertig ist mit dem letzten Befehl.

Jetzt ist die Frage, ob ich mit einen Zeichenpuffer mit 80 Zeichen 
anlege und per Timer-Interrupt immer im bestimmten Abstand das ganze 
Array nacheinander durchtickere, also quasi
1
ISR
2
{
3
  disp_out( buffer[counter++] );
4
}
oder ob ich wirklich die Sachen nur ans Display schicke, wenn ich es 
auch gerade verändern will. Da dann also
1
jump_to( 1, 5 );
2
disp_string_out( "TESTSTRING" );

In der ersten Variante würde ich zwei 80-Zeichen-Buffer nehmen. In den 
einen schreibe ich meine Daten, der andere dient der ISR als 
Datenquelle. Nach einem abgeschlossenen Buffer-Transfer dann den neuen 
Bufferinhalt rüberkopieren. Hier könnte ich ohne Busy-Flag arbeiten, 
indem ich ein Intervall nehme, welches länger als die Verarbeitungszeit 
des Displays ist.

Bei der zweiten Variante würde ich halt nach jedem Zeichen aufs 
Busy-Flag warten, wodurch ich durchs
1
while( LCD_BUSY );
Wartezyklen im Code habe.

Mir ist klar, dass die Wartezeiten hier nicht sehr groß sind, jedoch 
geht es mir mehr um die "schönere" Variante. Was meint ihr, bzw. was 
bevorzugt ihr und warum?

Gruß, Denis

von Falk B. (falk)


Lesenswert?

@ Denis (Gast)

>Ich arbeite mit dem Busy-Flag, also ohne Delays. Obwohl das Busy-Flag
>natürlich auch einem Delay gleichkommt, da ich ja warten muss, bis das
>Display fertig ist mit dem letzten Befehl.

Eben, das spart kaum was.

>Jetzt ist die Frage, ob ich mit einen Zeichenpuffer mit 80 Zeichen
>anlege und per Timer-Interrupt immer im bestimmten Abstand das ganze
>Array nacheinander durchtickere, also quasi

Kann man machen. Hat den Vorteil, dass das Programm sehr schnell Daten 
in den "Framebuffer" schreiben kann.

>oder ob ich wirklich die Sachen nur ans Display schicke, wenn ich es
>auch gerade verändern will. Da dann also

>jump_to( 1, 5 );
>disp_string_out( "TESTSTRING" );

Ist auch eine Möglichkeit, wenn man vorher prüfen kann, ob sich 
angezeigte Werte geändert haben, nur dann überschreibt man Teile des 
LCDs.

>In der ersten Variante würde ich zwei 80-Zeichen-Buffer nehmen. In den
>einen schreibe ich meine Daten, der andere dient der ISR als
>Datenquelle. Nach einem abgeschlossenen Buffer-Transfer dann den neuen
>Bufferinhalt rüberkopieren. Hier könnte ich ohne Busy-Flag arbeiten,
>indem ich ein Intervall nehme, welches länger als die Verarbeitungszeit
>des Displays ist.

Genau.

>Mir ist klar, dass die Wartezeiten hier nicht sehr groß sind, jedoch
>geht es mir mehr um die "schönere" Variante. Was meint ihr, bzw. was
>bevorzugt ihr und warum?

Ist eine Frage der Anwendung. In meinem aktuellen Prokelt habe ich ein 
kleines Menu. Die statemachine dazu wird alle 10ms aufgerufen und 
durchlaufen. Am Ende werden alle Anzeigeparameter auf eine Veränderung 
geprüft. Ist die positiv, gibt es einen Update des gesamten LCD. Für 
diese Sache ausreichend.

Wenn die Menus komplexer werden, könnte es sein, dass viele Stellen im 
Programm auf das LCD schreiben. Dann ist ggf. die 1. Variante besser. So 
oder so muss man aber sinnvollerweise dafür sorgen, dass das LCD nicht 
zu oft neu beschrieben wird, weil man dann ggf. nur flimmernde Zeichen 
hat die keiner ablesen kann. Ausserdem sind die klassischen LCDs nicht 
sonderlich schnell, die verschwimmen bei einem Dutzend Hz 
Wiederholfrequenz. Erst recht, wenn es kalt wird.

von Eduardo Mario (Gast)


Lesenswert?

Hi,
Ich habe mein eigenes kooperatives Multitasking geschrieben, da kann ich 
Busy Waits nicht brauchen. habe dann auch einen Display Manager 
implementiert, der mir jede meiner 4 Zeilen verwaltet. Damit kann ich 
dann z.b in die Zeile 4 Debug Infos von irgendeinem anderen interrupt 
ausgeben.
es hängt also davon ab, was du brauchst bzw in Zukunft brauchen wirst.
LG, Mario

von W.S. (Gast)


Lesenswert?

So sehr lang sind die Wartezeiten ja auch nicht.
also es kommt drauf an, was der Rest deines Programmes tun soll. Hast du 
genug Zeit, dann frag das Busy-Flag überhaupt nicht ab, sondern warte 
einfach pauschal ein paar Mikrosekunden. Hast du extrem wenig oder gar 
keine Zeit, dann schaufele deinen Text in einen String und versuche in 
der Grundschleife deines Programmes, selbigen ins Display zu bekommen.

immerzu:
 if (lcdnotbusy && nochwasauszugeben) GibEsAus();
 machdensonstigenkram();
goto immerzu;


W.S.

von Denis (Gast)


Lesenswert?

Hey!

Danke für die schnellen Antworten. Wie handhabt ihr das denn mit den 
Signalzeiten? Für den Enable-Puls (high-Zeit) sind im Datenblat z.B. min 
1us angegeben. Ich arbeite mit 8MHz. Da ist ein Takt gerade mal 125ns. 
Also 8 mal schneller. Und acht Takte dauert ein High->Low nicht. Macht 
ihr da auch Delays rein?

von Denis (Gast)


Lesenswert?

Edit: ist ja noch schlimmer, die 125ns sind ja high und low vom uC, also 
sogar nur halb so lang high

von Karl H. (kbuchegg)


Lesenswert?

Denis schrieb:

> Danke für die schnellen Antworten. Wie handhabt ihr das denn mit den
> Signalzeiten? Für den Enable-Puls (high-Zeit) sind im Datenblat z.B. min
> 1us angegeben. Ich arbeite mit 8MHz. Da ist ein Takt gerade mal 125ns.
> Also 8 mal schneller. Und acht Takte dauert ein High->Low nicht. Macht
> ihr da auch Delays rein?

Natürlich.
Tatsächlich ist neben falscher Verkabelung das Nichteinhalten der 
Mindestzeiten bei der LCD Steuerung eine der Hauptursachen hier im 
Forum, warum eine LCD-Ansteuerung nicht funktioniert.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

>> Also 8 mal schneller. Und acht Takte dauert ein High->Low nicht. Macht
>> ihr da auch Delays rein?
>
> Natürlich.
> Tatsächlich ist neben falscher Verkabelung das Nichteinhalten der
> Mindestzeiten bei der LCD Steuerung eine der Hauptursachen hier im
> Forum, warum eine LCD-Ansteuerung nicht funktioniert.

Aber es ist nicht so schlimm, wie sich das jetzt anhört. Denn 
tatsächlich ist eine Ausgabe auf ein LCD etwas, dass aus Sicht des µC 
nur alle 'heiligen Zeiten' mal passiert. Mehr als 3 oder 4 Updates pro 
Sekunde sind aus ergonomischer Sicht auf einem LCD nicht sinnvoll, weil 
sowieso kein Mensch eine Zahl ablesen kann, die sich schneller als das 
verändert.

Arbeitest du das ganze Jahr über durch und machst Weihnachten mal eine 
halbe Stunde Pause, dann wirkt sich das auf die Jahresarbeitszeit so gut 
wie gar nicht aus.

von Denis (Gast)


Lesenswert?

Das ist klar. Mir geht es ja auch nicht darum, dass die Updaterate 
möglichst hoch ist. Ich will nur nicht unbedingt die halbe Zeit der 
Displayansteuerung mit warten verbringen. Auch wenn es zeitlich 
sicherlich kein großes Ding ist.

Wie gesagt, mir geht es eher um die eleganteste Lösung. Deshalb wollte 
ich mal fragen, wie ihr das löst.

von Karl H. (kbuchegg)


Lesenswert?

Denis schrieb:
> Das ist klar. Mir geht es ja auch nicht darum, dass die Updaterate
> möglichst hoch ist. Ich will nur nicht unbedingt die halbe Zeit der
> Displayansteuerung mit warten verbringen.

Genau darum geht es.
Es ist eben nicht die 'halbe Zeit', sondern 'ferner liefen'

> Wie gesagt, mir geht es eher um die eleganteste Lösung.

Das ist immer so eine Sache. Eleganz liegt zu einem nicht unerheblichen 
Teil im Auge des Betrachters :-)

Persönlich hab ich bis jetzt die Framebufferlösung noch nie benutzt (und 
auch noch nie vermisst). Ich weiß aber, dass es sie gibt (und 
klarerweise auch wie man sie implementiert). Für mich hat sich daraus 
noch nie ein erkennbarer Vorteil ergeben und mit den paar Verzögerungen 
konnte ich bisher leben, sprich - sie waren unmerkbar gering.

von holger (Gast)


Lesenswert?

>Wie gesagt, mir geht es eher um die eleganteste Lösung. Deshalb wollte
>ich mal fragen, wie ihr das löst.

Ich hab mal ne State Maschine für eine 4 Bit Ansteuerung
geschrieben die ohne Delays auskommt. Das Programm
selbst war mein Delay. Benutzt hab ich das aber nie.
Bei den meisten Programmen tuts halt ein kleines Delay.

von holger (Gast)


Lesenswert?

>Persönlich hab ich bis jetzt die Framebufferlösung noch nie benutzt (und
>auch noch nie vermisst). Ich weiß aber, dass es sie gibt

>Ich hab mal ne State Maschine für eine 4 Bit Ansteuerung
>geschrieben die ohne Delays auskommt.

Da wurde logischerweise auch ein Framebuffer benutzt.
Irgendwie cool das ganze, aber den Code würde ich keinem
Noob geben;) Da kommen zu viele Missverständnisse auf.
Die meisten kommen ja nicht mal mit der Standard Lösung klar.

von Denis (Gast)


Lesenswert?

Alles klar Leute!

Ich danke euch für heute. Ich werde jtzt mal die einzelnen Varianten 
testen und gucken, was mit am Ende besser gefällt. Ich werde berichten.

von Thomas_H (Gast)


Lesenswert?

Bei mir wird ein Buffer benutzt.

Ein Timer-Interrupt mit 1 ms schickt jeweils zwei halbe Bytes (4-bit 
Schnittstelle) ohne Warteschleife zwischen den Nibbles zum Display. Die 
Anfangsadressen der Zeilen werden dabei gleich mit korrigiert.

Aus Sicht des Hauptprogramms ist das LCD damit ein Bereich im RAM.

von Peter D. (peda)


Lesenswert?

Wenn man aus verschiedenen Programmteilen auf das LCD schreibt, ist die 
Interruptmethode besser.
Man spart sich das ewige Positionieren des Kursors und muß nicht drauf 
achten, zu oft auszugeben.
Einen 2.Puffer braucht man nicht.

Hier ein Beispiel:

Beitrag "Formatierte Zahlenausgabe in C"

von Denis (Gast)


Lesenswert?

Habe ich denn mit einem Puffer nicht unter Umständen das Problem, dass 
ich gerade was ändere, während es ausgegeben wird. Dann könnte ich halb 
neuen, halb alten Text in der Zeile haben.

von Falk B. (falk)


Lesenswert?

Kann passieren. Muss man halt oft genug einen Update machen, so 3-10Hz.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Denis schrieb:
> Habe ich denn mit einem Puffer nicht unter Umständen das Problem, dass
> ich gerade was ändere, während es ausgegeben wird. Dann könnte ich halb
> neuen, halb alten Text in der Zeile haben.
Das war bei den alten PCs schon so. Wenn dort direkt in den 
Bildschirmspeicher geschrieben wurde, dann war für ein paar ms noch der 
halbe alte und schon der halbe neue Inhalt zu sehen. Keine Problem: da 
kommt das Auge nicht mit...
Wenn auf einem 20x4 Display jede ms 1 Zeichen geschrieben wird (die 
langsamen Befehle clear display und return home braucht man nicht, 
man dreht ja nur an der DDRAM Adresse), dann kommt man mit 80 ms auf 
12Hz Updaterate, und das reicht auf jeden Fall aus. Und weil die Zeichen 
nur überschrieben werden, gibt es das bekannte Flackern nicht. Das tritt 
ja nur auf, wenn vor dem Schreiben erst mal das Display gelöscht wird.

Ich nehme einen Bildschirmspeicher im Controller, kopiere den laufend 
aufs Display und kann auf diese Art sogar eine Art Paging machen: im 
Speicher mehrere Bildschirmseiten beschreiben und nur eine davon 
anzeigen. Da klappt sogar Scrollen ganz einfach: ich lege 40 
Bildschirmzeilen an und gebe 4 davon aufs Display aus...

von c-hater (Gast)


Lesenswert?

Denis schrieb:

> Mir ist klar, dass die Wartezeiten hier nicht sehr groß sind, jedoch
> geht es mir mehr um die "schönere" Variante. Was meint ihr, bzw. was
> bevorzugt ihr und warum?

Ich benutze einen Kommandopuffer (also keinen Framepuffer) und einen 
Timerinterrupt mit einer Periode des 1..4fachen der kürzesten "langen" 
Wartezeit des LCD. Alle längeren Wartezeiten werden als Vielfache der 
Basisperiode ausgedrückt (die richtigen Faktoren werden zur Entwurfszeit 
berechnet).

Der Kommandopuffer ist als Ringpuffer ausgeführt und nichtblockierend 
(von einer nur wenige Takte langen Synchronisationssequenz abgesehen).

Vorteile:
-Schreiben ist zu jeder Zeit möglich, also auch direkt aus ISRs.
-Jede geschriebene Kommandosequenz ist "atomar", kommt also entweder 
ganz
 und ungestört beim Display an oder garnicht.
-Timerinterrupt kann fast immer als "Zweitverwertung" implementiert 
werden.

Nachteil:
-Kommandopuffer ist zwar konfigurierbar, aber auf jeden Fall endlich. 
D.h.:
 es kann die Situation eintreten, daß eine Kommandosequenz nicht 
abgesetzt
 werden kann.

von Thomas W. (Gast)


Lesenswert?

Denis schrieb:
> Ich will nur nicht unbedingt die halbe Zeit der
> Displayansteuerung mit warten verbringen. Auch wenn es zeitlich
> sicherlich kein großes Ding ist.

Mußt du doch auch nicht. Wenn der µC auch noch andere Dinge zu tun hat, 
kannst du die immer zwischen schieben. Wenn du die Ausgabe-Task in so 
großen Zeitabständen triggerst, dass der Display-Controller garantiert 
fertig ist, braucht da niemand zu warten. Und wegen 1µs Enable-Puls, 
lohnt es nicht, irgendwelchen Zirkus zu veranstalten, nur um da um die 
Wartezeit.
Die "halbe Zeit" mußt du also überhaupt nicht waren. Wenn du die 
Befehlsdauer, gemessen in deinem Task-Takt halbwegs gut abschätzen 
kannst. Ansonsten lohnt es, wie schon gesagt, an der Stelle nicht 
beliebig rumzuoptimieren. Insgesamt fällt die Prozessorlast nicht auf 
und solange du programmtechnisch dafür sorgst, dass andere Dinge nicht 
im Ablauf gestört werden und die Ausgabe so selten erfolgt, dass der 
Betrachter nicht durch wildes Flackern genervt wird, ist alles gut.

von Stephan (Gast)


Lesenswert?

Thomas_H schrieb:
> Bei mir wird ein Buffer benutzt.
>
> Ein Timer-Interrupt mit 1 ms schickt jeweils zwei halbe Bytes (4-bit
> Schnittstelle) ohne Warteschleife zwischen den Nibbles zum Display. Die
> Anfangsadressen der Zeilen werden dabei gleich mit korrigiert.
>
> Aus Sicht des Hauptprogramms ist das LCD damit ein Bereich im RAM.

genau so mache ich das auch. Bin damit immer gut gefahren.
Ist aber nicht immer die Lösung der Wahl. Kommt immer auf den Zweck an 
und ob man genug Speicher dafür hat.

von Falk B. (falk)


Lesenswert?

Und wenn man ein etws moderneres LCD wie z.B die DOGM nimmt, steuert man 
die mit SPI an. Dort gibt es kein Busy Flag mehr! Dann feuert man 
einfach ein einzelnes Byte raus (bis zu 4 Mbit/s) und fertig. Macht 
bischen mehr als 2us/Bytes, also praktisch nix.

von Peter D. (peda)


Lesenswert?

c-hater schrieb:
> D.h.:
>  es kann die Situation eintreten, daß eine Kommandosequenz nicht
> abgesetzt
>  werden kann.

Und was ist dann der Vorteil daran?

Mit dem Framepuffer kann das nicht passieren.
Jede Ausgabetask schreibt direkt in den SRAM an die Stelle, wo der Text 
erscheinen soll.

von Nosnibor (Gast)


Lesenswert?

Also wenn man schon auf BUSY warten will, dann doch gefälligst vor der 
Ausgabe eines Zeichens und nicht hinterher. Es sei denn, man wollte 
unbedingt sicherstellen, daß immer nur einer von beiden gleichzeitig 
arbeitet: das Display oder der Prozessor.

von Wilhelm F. (Gast)


Lesenswert?

Ich tendiere dazu, ein LCD-Display in Zeitrastern zu schreiben, z.B. 
alle 200ms, viel schneller kann das Auge sowieso nicht betrachten.

Bei meiner DCF77-Uhr gibt es ein vollständiges Display-Update jede 
Sekunde, das reicht dort.

Ich gewöhnte mit auch an, stets das gesamte Display zu refreshen, der 
Inhalt steht immer in einem Spiegelrambereich, und der wird einmal 
vollständig ausgelöst.

In den Anfangsbastelzeiten schrieb ich ja noch beliebig nicht 
zeitsynchron einzelne Zeichen ins Display. Das gibt aber häßliche 
Flimmereffekte bei etwas seitlicher Betrachtung, und dazu fand ich 
später in Literatur auch den Hinweis, daß man den Inhalt genau deswegen 
komplett updatet.

Mit dem Busy-Flag lief ich auch schon mal Ausfällen auf. Ein Stecker vom 
µC zum Display hatte einen Wackler, dann bleibt alles µC und Display 
stehen. Dort wählt man evtl. doch besser die Wartezeitmethode, oder 
einen Timeout-Timer, falls das Busy-Flag nicht im erwarteten Zeitraum 
kommt.

Aber im Grunde, zur Threadfrage, macht man es so, wie man es braucht. Es 
gibt wohl keine Universallösung.

von Wusel D. (stefanfrings_de)


Lesenswert?

Meine Displays flackern unangenehm, wenn man sie ständig neu beschreibt. 
Auch wenn ich immer wieder die gleichen Zeichen übertrage.

Das würde ich also besser lassen. Übertrage nur dann, wenn sich die 
Anzeige ändert.

von holger (Gast)


Lesenswert?

>Meine Displays flackern unangenehm, wenn man sie ständig neu beschreibt.

Dann machst du was falsch;)
Finger weg vom ClearScreen Befehl.

: Wiederhergestellt durch Moderator
von Wilhelm F. (Gast)


Lesenswert?

Stefan Nie schrieb:

> Meine Displays flackern unangenehm, wenn man sie ständig neu beschreibt.
> Auch wenn ich immer wieder die gleichen Zeichen übertrage.

Das schrieb ich ja bereits.

von c-hater (Gast)


Lesenswert?

Peter Dannegger schrieb:

> Und was ist dann der Vorteil daran?

Determinismus:
Der Caller erfährt, daß seine Ausgabe den Benutzer nicht erreichen wird 
und er erfährt auch, warum nicht. Er hat also z.B. die Option, wichtige 
Nachrichten selbst zu "puffern", um sie zu einem späteren Zeitpunkt 
loszuwerden. Unwichtige hingegen kann er einfach verwerfen.

Effizienz:
Wenn es hingegen nichts (neues) auszugeben gibt, sinkt der 
Rechenzeitverbrauch der Ausgabe auf einen unerheblichen Wert. Die Frage, 
ob die Queue leer ist, kostet nur zwölf Takte in der Timer-ISR.

Universalität:
Das Schema handelt auch problemlos die Initialisierung ab oder das 
Setzen von Custom-Zeichen, diese Sachen wahlweise sogar parallel für 
mehrere Controller gleichzeitig. Bei zwei 4x27-Displays von Pollin steht 
man also nicht eine gute halbe Sekunde im Dunkeln, weil die vier 
Controller der zwei Displays initialisiert werden müssen. Das dauert 
vielmehr genauso lange, als wäre es nur ein Controller. Und natürlich 
kann der Atmel in der ganzen Zeit auch schon andere Sachen tun, und 
dabei sogar Ausgaben an die noch garnicht fertig initialisierten 
Displays tätigen. Solange halt der Kommandopuffer reicht.

Und dessen Größe ist, wie schon gesagt, konfigurierbar. Im schlimmsten 
Fall, wenn man nicht in der Lage ist, die Mitteilungswut seiner 
Programme zu zähmen, muß man halt einfach einen größeren Controller 
nehmen. Das wäre wohl die Lösung der C-Programmierer...

von Bastler (Gast)


Lesenswert?

Wieso eigentlich c-hater und nicht "alles was man so sinnvoll machen 
würde"-hater?

von Peter D. (peda)


Lesenswert?

c-hater schrieb:
> Er hat also z.B. die Option, wichtige
> Nachrichten selbst zu "puffern", um sie zu einem späteren Zeitpunkt
> loszuwerden. Unwichtige hingegen kann er einfach verwerfen.

Ach Du meine Güte.
Das wäre mir viel zu kompliziert, bei jeder Ausgabe extra noch den 
Returnwert abfragen und behandeln zu müssen.
Ich mag nicht gerne den Code unnütz aufblähen und das Programm 
unübersichtlicher machen.
Im Framebuffer verwerfen sich veraltete Ausgaben automatisch (werden 
überschrieben), ganz ohne jede zusätzliche Codezeile.


c-hater schrieb:
> Wenn es hingegen nichts (neues) auszugeben gibt, sinkt der
> Rechenzeitverbrauch der Ausgabe auf einen unerheblichen Wert.

Ginge mit Framebuffer auch.
Aber da die CPU-Last eh <1% ist, lohnt sich der zusätzliche Aufwand 
einfach nicht.
Jede Ausgabe müßte dann eine Variable auf die Puffergröße setzen und der 
Interrupt müßte sie testen und auf 0 runter zählen.


c-hater schrieb:
> Bei zwei 4x27-Displays von Pollin steht
> man also nicht eine gute halbe Sekunde im Dunkeln, weil die vier
> Controller der zwei Displays initialisiert werden müssen.

Das LCD-Init mache ich bequemer Weise gleich im Init, ohne Interrupts 
mit Delay.
Ich hab dann zwar den Code für die Byteausgabe doppelt, spare aber durch 
die viel einfachere Verwaltung umso mehr Code ein.

Habe ich mehrere LCD-Controller, lege ich alle E-Signale auf einen Port 
und speichere in einer Variable die Maske dafür. Dann kann man bis zu 8 
Controller simultan initialisieren, spart ja Zeit und Flash.

von Dietmar (Gast)


Lesenswert?

Hallo Leute!

Ich krame mal diese etwas ältere, aber dennoch sehr interessante 
Geschichte wieder aus - ich stehe gerade vor der selben Frage...und die 
Interruptlösung finde ich ganz chick, zumindest erstmal gedanklich.

Aber eine Frage habe ich dazu noch (bevor ich losprogrammiere und am 
Ende alles wieder lösche, weil ich das gewünschte nicht erreiche):

Wenn ich das Display auch für Eingaben nutzen will und dann zum Beispiel 
in einer Zeile stehen habe "SET VOLTAGE: 00.0 V" und möchte jetzt per 
Encoder oder was auch immer den Wert 00.0 ändern, dann würde es sich 
anbieten, wenn ich den Cursor, welcher mir ja direkt zu jedem Zeichen 
migeliefert wird, benutze. Also würde dann zum Beispiel bei einem 
Tastendruck der Cursor unter der ersten 0 aufleuchten, damit ich weiß, 
dass ich eben grad an dieser Stelle bin.

ABER: Wenn ich einen Framebuffer kontinuierlich ausgebe, dann wird beim 
HD44780 doch auch nach jedem Zeichen die DDRAM-Adresse inkrementiert und 
damit rutscht doch auch der Cursor immer eins weiter, oder täusche ich 
mich? Wie würde ich in dem Fall einen statischen Cursor unter der ersten 
0 bekommen? Jedesmal vor der entsprechenden Stelle ein- und ausschalten 
oder wie?

Hoffe, es ist klar, was ich meine.

Gruß, Dietmar

von spess53 (Gast)


Lesenswert?

Hi

>ABER: Wenn ich einen Framebuffer kontinuierlich ausgebe, dann wird beim
>HD44780 doch auch nach jedem Zeichen die DDRAM-Adresse inkrementiert und
>damit rutscht doch auch der Cursor immer eins weiter, oder täusche ich
>mich? Wie würde ich in dem Fall einen statischen Cursor unter der ersten
>0 bekommen? Jedesmal vor der entsprechenden Stelle ein- und ausschalten
>oder wie?

Cursor einfach nicht einschalten.

MfG Spess

von spess53 (Gast)


Lesenswert?

HI

>Cursor einfach nicht einschalten.

Man sollte langsam alles lesen. Bitte ignorieren.

MfG Spess

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Dietmar schrieb:
> Jedesmal vor der entsprechenden Stelle ein- und ausschalten
> oder wie?

Ja - oder danach, damit man den Cursor möglichst lange sieht, setze ich 
ihn beim Verlassen des LCD Refresh.

von Dietmar (Gast)


Lesenswert?

Matthias Sch. schrieb:
> Ja - oder danach

Ja sorry, dumm formuliert, natürlich vor der entsprechenden Stelle ein, 
und danach wieder ausschalten. Nur das würde bei einem Timer-Interrupt 
von sagen wir mal zwei Millisekunden nur eine sehr kurze Zeit sein, in 
der eben diese eine Stelle mit Cursor zu sehen ist.

Gibt es da ne elgantere Lösung, oder ist das Verfahren mit dem 
Framebuffer dafür schlichtweg ungeeignet?

von holger (Gast)


Lesenswert?

>Gibt es da ne elgantere Lösung, oder ist das Verfahren mit dem
>Framebuffer dafür schlichtweg ungeeignet?

Warum sollte der ungeeignet sein? Man könnte die Zahl selbst
z.B. blinken lassen indem man sie im Framebuffer in einem
zeitlichen Wechsel löscht und wieder einträgt.

von Dietmar (Gast)


Lesenswert?

holger schrieb:
> Man könnte die Zahl selbst
> z.B. blinken lassen indem man sie im Framebuffer in einem
> zeitlichen Wechsel löscht und wieder einträgt.

Ja klar, das ist die andere Variante. Die geht, war nur ne Frage wegen 
dem Cursor, weil ich Geräte hier stehen habe, bei denen es mit dem 
Cursor gemacht wird. Und bei genauerem Hinsehen habe ich gerade 
entdeckt, dass man in dem Display (2x20 Zeichen) irgendwie auch einen 
Durchlauf erkennen kann. Sehr schwach, aber sichtbar wenn man ganz nah 
dran geht und vom richtigen Winkel drauf guckt.

von Falk B. (falk)


Lesenswert?

@ Dietmar (Gast)

>Ja klar, das ist die andere Variante. Die geht, war nur ne Frage wegen
>dem Cursor,

Geht so nicht, weil dann das Blinken "durcheinander" kommt. Im 
Zweifelsfall, probier es aus, geht ja schnell.

> weil ich Geräte hier stehen habe, bei denen es mit dem
>Cursor gemacht wird.

Die machen halt keinen dauerhaften Refresh sondern nur bei Änderungen.

> Und bei genauerem Hinsehen habe ich gerade
>entdeckt, dass man in dem Display (2x20 Zeichen) irgendwie auch einen
>Durchlauf erkennen kann. Sehr schwach, aber sichtbar wenn man ganz nah
>dran geht und vom richtigen Winkel drauf guckt.

Das ist das Multiplexing vom LCD, das macht es selber. GGf. mit einer 
Interferenz von der LED-Hintergrundbeleuchtung, die vielleicht mit 
PWM arbeitet. Hab ich hier auch mit einem DOGM LCD. Fällt aber ur 
bei bestimmten Blickwinkeln auf.

von Stephan H. (stephan-)


Lesenswert?

ich benutze den Framebuffer bisher ausschließlich. Das gute daran ist 
für mich, das ich nicht zwischen Steuer und Nutzdaten unterscheiden 
muss.Ich lege die Bytes ab und sage mit einem Flag das es Steuer oder 
Nutzdaten sind. Allerdings kann das beim 8051 mit 128 Byte RAM und 
4x20er Display schnell eng werden. Ist rein eine Sache des persönlichen 
Geschmacks und der Anforderungen an das Timing der ges. Baugruppe.

das Blinken eines Cursors erfolgt dann logischer Weise im RAM !
20h, Wert, 20h, Wert .......... etc.pp logische Verknüpfungen

Ein Beispiel hatte ich mal in die Codesammlung gestellt.
Beitrag "Serielles LCD/Keypad Interface" .......... weiter unten

: Bearbeitet durch User
von Wolfgang (Gast)


Lesenswert?

Dietmar schrieb:
> Nur das würde bei einem Timer-Interrupt
> von sagen wir mal zwei Millisekunden nur eine sehr kurze Zeit sein, in
> der eben diese eine Stelle mit Cursor zu sehen ist.

Ich nehme mal an, dass du das Display für menschliche Benutzer und nicht 
für Fliegen benutzen möchtest. Dann reicht ein Update alle 1/10 s. Wenn 
du also, ggf. bei abgeschaltetem Cursor, das Gesamtdisplay 
aktualisierst, dann den Cursor auf das zu "cursernde" Zeichen stellst 
und anschaltest, hat er fast 100 ms Zeit zum leuchten, bei einem 
Duty-Cylce von über 90%.

von Stephan H. (stephan-)


Lesenswert?

der Denkfehler liegt darin, das der Cursorwechsel (blinken) auch mit 1ms 
geht, das das Display ja 16,32 oder mehr stellen hat, die ausgegeben 
werden, bevor der Cursor sein "Gesicht" 1 Mal wechselt.
Pro Interrupt wird ja nur EIN Zeichen ausgegeben.

: Bearbeitet durch User
von Dietmar (Gast)


Lesenswert?

Stephan Henning schrieb:
> Pro Interrupt wird ja nur EIN Zeichen ausgegeben.

Ja schon, aber in der nächsten Millisekunde kommt ja schon das nächste 
Zeichen, welches keinen Cursor merh hat, oder was verstehe ich grad 
nicht?

von Falk B. (falk)


Lesenswert?

@ Dietmar (Gast)

>Ja schon, aber in der nächsten Millisekunde kommt ja schon das nächste
>Zeichen, welches keinen Cursor merh hat, oder was verstehe ich grad
>nicht?

Er setzt den Cursor nach JEDER Zeichenausgabe auf die gleiche Stelle 
zurück. Aber ob das dann normal blinkt ist fraglich. Probieren.

von Dietmar (Gast)


Lesenswert?

Mhh...das geht doch aber eigentlich garnicht. Wenn ich an (nur mal 
beispielhaft) Stelle 5 von den gesamten 32 Stellen den Cursor haben will 
und nun einen Puffer von 32 Zeichen habe, dann lasse ich ja den gesamten 
Puffer von 0 bis 31 einmal komplett ausgeben, also wandert auch der 
Cursor einmal komplett durchs Display. Also nach jedem einzelnen Zeichen 
geht da ja eigentlich nicht, weil selbst wenn ich ihn händisch da hin 
stellen würde, dann wäre beim nächsten Zeicheninterrupt der Buchstabe an 
der falschen Stelle. Oder ich müsste dann erst wieder den Cursor auf die 
ursprüngliche Position bringen, damit es von da weiter geht.

Jetzt kommt mir grad mal die Frage auf, ob wir vom selben reden...mit 
einem Zeichen meine ich, dass alle 1ms ein Timer-Interrupt kommt, 
welcher genau einen Buchstaben aufs Display schreibt. Also in 32ms wäre 
dann das ganze Display geschrieben. Oder meint ihr per Interrupt einmal 
auslösen, dass alle 32 Zeichen geschrieben werden?

von Falk B. (falk)


Lesenswert?

@ Dietmar (Gast)

>Mhh...das geht doch aber eigentlich garnicht. Wenn ich an (nur mal
>beispielhaft) Stelle 5 von den gesamten 32 Stellen den Cursor haben will
>und nun einen Puffer von 32 Zeichen habe, dann lasse ich ja den gesamten
>Puffer von 0 bis 31 einmal komplett ausgeben,

Aber verteilt über 32 Interrupts.

>also wandert auch der
>Cursor einmal komplett durchs Display.

Nein. Den kann man vor der Ausgabe abschalten.

> Also nach jedem einzelnen Zeichen
> geht da ja eigentlich nicht, weil selbst wenn ich ihn händisch da hin
>stellen würde, dann wäre beim nächsten Zeicheninterrupt der Buchstabe an
>der falschen Stelle.

Jain, weil . . .

> Oder ich müsste dann erst wieder den Cursor auf die
>ursprüngliche Position bringen, damit es von da weiter geht.

Genau! Aber ganu dort wird es echt auswändig. Denn man müsste

Cursor ausschalten
Cursor neu setzen
neues Zeichen ausgeben
Cursor rücksetzen
Cursor einschalten

Macht satte 5 Befehle a 40us, sprich 200us. Damit sind 20% des 1ms 
Timerintervalls mehr oder weniger sinnlos mit Warten vertrödelt. Nicht 
wirklich gut. Eine Softwareemulation ist hier deutlich effizienter. 
Zumal die Hardwareversion (LCD blink den Cursor selber) wahrscheinlich 
nicht funktioniert, wegen der vielen Cursorzugriffe.

>Jetzt kommt mir grad mal die Frage auf, ob wir vom selben reden...mit
>einem Zeichen meine ich, dass alle 1ms ein Timer-Interrupt kommt,
>welcher genau einen Buchstaben aufs Display schreibt.

Ja.

> Also in 32ms wäre
>dann das ganze Display geschrieben.

Genau.

>Oder meint ihr per Interrupt einmal
>auslösen, dass alle 32 Zeichen geschrieben werden?

Nein.

von Stephan (Gast)


Lesenswert?

Falk Brunner schrieb:
> Jain, weil . . .
>
>> Oder ich müsste dann erst wieder den Cursor auf die
>>ursprüngliche Position bringen, damit es von da weiter geht.
>
> Genau! Aber ganu dort wird es echt auswändig. Denn man müsste
>
> Cursor ausschalten
> Cursor neu setzen
> neues Zeichen ausgeben
> Cursor rücksetzen
> Cursor einschalten


neee neee.
Ich toggle die RAM Zelle, so das es entweder der Zahlenwert ist oder 
eben
20h für ein Leerzeichen oder einen Block FFh. Ein Cursor wäre genauso 
gut möglich. Das toggeln mache ich dann aber im Sekundentakt.

von Falk B. (falk)


Lesenswert?

@ Stephan (Gast)

>>> Oder ich müsste dann erst wieder den Cursor auf die
>>>ursprüngliche Position bringen, damit es von da weiter geht.
>
>> Genau! Aber ganu dort wird es echt auswändig. Denn man müsste

>> Cursor ausschalten
>> Cursor neu setzen
>> neues Zeichen ausgeben
>> Cursor rücksetzen
>> Cursor einschalten

Ich meinte hiermit, wenn man die Cursorfunktion des LCDs nutzen will.

>neee neee.
>Ich toggle die RAM Zelle, so das es entweder der Zahlenwert ist oder
>eben
>20h für ein Leerzeichen oder einen Block FFh. Ein Cursor wäre genauso
>gut möglich. Das toggeln mache ich dann aber im Sekundentakt.

Du meinst eine Cursorfunktion in der uC Software. Das ist was anderes 
und hier deutlich sinnvoller.

von Dietmar (Gast)


Lesenswert?

Vielen Dank!

Ich werde auf den LCD-Cursor verzichten! Ich werde ebenfalls den 
Software-Cursor verwenden, entweder blank oder voll gefüllt - mal 
schauen, was besser aussieht.

Jetzt teste ich das mal, dann melde ich mich nochmal.

von Stephan H. (stephan-)


Lesenswert?

Falk Brunner schrieb:
> @ Stephan (Gast)
>

> Ich meinte hiermit, wenn man die Cursorfunktion des LCDs nutzen will.
>
>>neee neee.
>>Ich toggle die RAM Zelle, so das es entweder der Zahlenwert ist oder
>>eben
>>20h für ein Leerzeichen oder einen Block FFh. Ein Cursor wäre genauso
>>gut möglich. Das toggeln mache ich dann aber im Sekundentakt.
>
> Du meinst eine Cursorfunktion in der uC Software. Das ist was anderes
> und hier deutlich sinnvoller.


Jepp, alles klar.
Auf die Idee den vom LCD zu nutzen würde ich gar nicht kommen, um den 
muss ich mich ja kümmern. Da bin ich viel zu faul zu.  :-))

: Bearbeitet durch User
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.