Hallo Forum, ich habe eine Verständisfrage: An einem Atmeg8 ist ein LCD im 4-Bit Modus (Code im Anhang) angeschlossen. Auf dem LCD soll ein Lauftext ausgegeben werden und kontinuierlich durchlaufen. Mehr nicht. Allerdings funktioniert das nicht wie gewünscht. Anstatt den Text nacheinander aus dem Speicher zu lesen, ist immer ein "Offset" von 5 dazwischen. Der Text läuft also nicht, sondern springt. Codeauszug: .org 0x200 text: .db "_____Atmega_____";1 Position bei der Ausgabe .db "____Atmega______";14 .db "___Atmega_______";11 .db "__Atmega________";8 .db "_Atmega_________";5 .db "Atmega__________";2 .db "tmega__________A";15 .db "mega__________At";12 .db "ega__________Atm";9 .db "ga__________Atme";6 .db "a__________Atmeg";3 .db "__________Atmega";16 .db "_________Atmega_";13 .db "________Atmega__";10 .db "_______Atmega___";7 .db "______Atmega____";4 .db 0 Aber warum ist das so? Was mache ich falsch? Ich denke mein Problem hat mit dem Verständis des LPM-Befehls bzw. der Speicherorganisation zu tun. Die Erklärungen im AVR-Tutorial bzw. bei der Googlesuche waren hier leider auch nicht dienlich. Wäre für Aufklärung dankbar Grüße Der Tobi
Du meinst shiften/scrollen? Hatte ich auch schon probiert, allerdings hats auch nicht funktioniert. Weiß allerdings nicht obs richtig war: Habe das LCD mit dem Text "Atmega" geladen und anschließend in Endlosschleife gescrollt.
Tobi schrieb: > Habe das LCD mit dem Text "Atmega" geladen und anschließend in > Endlosschleife gescrollt. Wenn der Text rausgefallen ist musst du natürlich hinten was Lesbares nachschieben. Das LCD ist ja kein Ringspeicher. Tobi schrieb: > Auf dem LCD soll ein Lauftext ausgegeben werden und kontinuierlich > durchlaufen. Mehr nicht. Muss das in Assembler sein?
Woher weiß ich den wann ich aus dem sichtbaren Bereich geschoben habe? Und ja ich kann nur Assembler. Mich würde trotzdem interessieren woher der bechrieben "Offset" aus meinem Eingangspost herkommt?
Tobi schrieb: > Woher weiß ich den wann ich aus dem sichtbaren Bereich geschoben habe? Durch einfache Rechenvorgänge mit den Grunddaten die du kennst: - LCD Zeilenbreite - Stringlänge - aktuelle Shift-Position
Hi >haupt1: > ldi zl,low(2*text) > ldi zh,high(2*text) > haupt: > lpm temp1, Z+ > cpi temp1,0 > breq haupt1 !!! nach dieser Stelle sollte auch der Adress- zähler des Displays auf Null gestellt werden >Muss das in Assembler sein? Warum nicht? Oder hast du etwas gegen Assembler? MfG Spess
Wieviele Zeichen hat das Display pro Zeile? Füllt der Text alle Zeichen aus?
Tobi schrieb: > Du meinst shiften/scrollen? > Hatte ich auch schon probiert, allerdings hats auch nicht funktioniert. (Entry Mode Shift Set Einstellung bringt das besagte Prob.) Hi, um das Problem mit den "virtuellen" Adressen des LCD zu umgehen, mach einmal für jede Zeile eine Tabelle: die 16 Zeichen (also für jede einzelne Zeile von Anfang bis Ende) enthält und mit Nullterminierung pro Zeile. zum Beispiel (verkürzt): Tabelle: .db "Atmega",0 und dann vorne ein Leerzeichen, hinten ein Buchsabe raus .db " Atmeg",0 n+1 , n+2....etc. Dann, falls das mit dem lpm und Z+ nicht geht: zu Fuß:
1 | print: |
2 | lpm ; erstes Byte des Strings nach R0 lesen |
3 | tst R0 ; R0 auf 0 testen |
4 | breq print_end ; wenn 0, dann zu print_end |
5 | mov temp, r0 ; Inhalt von R0 nach temp kopieren |
6 | rcall ausgabe |
7 | adiw ZL:ZH, 1 ; Adresse des Z-Pointers um 1 erhoehen |
8 | rjmp print ; zum Anfang springen, um naechstes |
9 | ; ; Byte aus dem cseg-Label |
skizziert als Denkanstoß. Und evtl. ein "Display Clear" hinter jedem Print. (Die Initialisierung muss dann als "labels" ausgeführt werden, um einzelne Funktionen hier "Display clear" separat aufrufen zu können.) Man kann auch 16 x Leerzeichen 0x20 als Tabelle senden. Dann flackert das Display allerdings vielleicht mehr . Also, wie gesagt nur e i n e Zeile betrachtet. Am Anfang des Tabellenstrings noch eine Positionierungsangabe Also "springe an Anfang Zeile 1": Kommandomdus und 0x80 übergeben. Soll auch die zweite Zeile geshiftet werden, muss noch mit weiteren separaten Positionierungen gearbeitet werden. Kann noch etwas dauern, bis ich das ausprobiert habe. Bitte um etwas Geduld. ciao gustav
:
Bearbeitet durch User
Ein 16x 2 Display verwendet den selben Ansteuerchip, wie ein 20x 2 Display. es ist also ein 20x 2, das aber nur 16 Stellen darstellt. So erklärt sich dein Offset ;-)
Gerald B. schrieb: > Ein 16x 2 Display verwendet den selben Ansteuerchip, wie ein 20x 2 > Display. es ist also ein 20x 2, das aber nur 16 Stellen darstellt. So > erklärt sich dein Offset ;-) Genau, deswegen die Idee mit der Tabelle: Karl B. schrieb: > um das Problem mit den "virtuellen" Adressen des LCD zu umgehen, > mach einmal für jede Zeile eine Tabelle: > die 16 Zeichen (also für jede einzelne Zeile von Anfang bis Ende) > enthält und mit Nullterminierung pro Zeile. spess53 schrieb: >> breq haupt1 !!! nach dieser Stelle sollte auch der Adress- > zähler des Displays auf Null gestellt werden > >>Muss das in Assembler sein? > > Warum nicht? Oder hast du etwas gegen Assembler? Hi, Der Tabellenstring wird über die (16-Bit)Pointeradressierung davor aufgerufen. wieso sollte der Adresszähler des LCD damit etwas zu tun haben? Oder habe ich da etwas falsch aufgefasst? Karl B. schrieb: > Also, wie gesagt nur e i n e Zeile betrachtet. > Am Anfang des Tabellenstrings noch eine Positionierungsangabe > Also "springe an Anfang Zeile 1": > Kommandomdus und 0x80 übergeben. ciao gustav
:
Bearbeitet durch User
Karl B. schrieb: > wieso sollte der Adresszähler des LCD damit etwas zu tun haben? > Oder habe ich da etwas falsch aufgefasst? Weil die Cursor-Adresse immer weiter zählt, und zwar viel weiter als die Display-Zeile lang ist.
Uhrmacher schrieb: > Weil die Cursor-Adresse immer weiter zählt, und zwar > viel weiter als die Display-Zeile lang ist. OK, dem SRAM ist das egal, es wird was rausgeholt und z.B. auch über RS232 UART ausgegeben. Für die Lösung des "Problems" die Cursor-Adresse via Positionierung- alias Locate-Anweisung wie schon erwähnt separat programmieren. ciao gustav
Hallo zusammen, werde heute abend eure Vorschläge probieren. Bin jetzt aber erstmal unterwegs. Grüße der Tobi
Hi, 'mal eine Quick-and-dirty-Lösung (mit dem ATiny4313 - der lpm Z+ Befehl geht da.) viel Spaß ciao gustav
Karl B. schrieb: > mal eine Quick-and-dirty-Lösung Vierundzwanzig Funktionsaufrufe und vierundzwanzig Funktionen für vierundzwanzig Strings .... Ja, das ist wirklich dööörty.
Karl B. schrieb: > Und evtl. ein "Display Clear" hinter jedem Print. Das dadurch verursachte Flackern auf dem Display versucht man gewöhnlich zu vermeiden.
Uhrmacher schrieb: > dööörtier hätt' ich es auch nicht hinbekommen Hi, eine Lösungsmöglichkeit, nicht die optimale. Also, die Tabellenlösung -> ja/nein =>ja wie man sieht ziemlich speicherfressend. Mit dem Shift set des LCD selbst zu operieren? Es passiert folgendes: Die Buchstaben werden immer auf dieselbe Stelle geschrieben. Oder: Cursor-Bewegung (Adressenincrement) muss drin bleiben. Die andere Idee wäre, Locate-Anweisungen innerhalb der Tabellenroutine bis zum sichtbaren Display-Adressbereich-Ende incrementieren, dann Sprung zu Anfang des Adressbereichs. Oder: Mehrere Tabellen, einmal für Text /Ascii selbst , dann alternierend für die Locate-Anweisungen. Da kann man noch basteln.... ciao gustav
Displayshift, mitlaufender Zähler für Cursorposition und die Zeile bei bedarf, außerhalb des Displays befüllen. Gern in einem rutsch, das geht so schnell da ruckelt nix. Nich vergessen das olle Zeugs kommt wieder.
Wolfgang schrieb: > Das dadurch verursachte Flackern auf dem Display versucht man gewöhnlich > zu vermeiden. Karl B. schrieb: > Und evtl. ein "Display Clear" hinter jedem Print. >..... > Dann flackert das Display allerdings vielleicht mehr. Hi, yep. Wie schon im Nachsatz oben erwähnt. Deswegen ist's im angehängten Prog. auch nicht verwendet worden. Teo D. schrieb: > mitlaufender Zähler für Cursorposition und die Zeile bei > bedarf, außerhalb des Displays befüllen. Genau so eine Idee wie die mit der mit dem Incrementieren einer Locate-Anweisung in der Tabellenroutine. Dann mit cpi bis hex 0x8F Hat nur den Nachteil, dass das, was davor steht, nicht überschrieben wird. Das Display speichert einmal eingegebene Characters. Sonst würde z.B. das im anderen Thread Beitrag "Re: LCD auf Steckbrett, Störungen" mit Bild gezeigte "Messgeräteprog." nicht funktionieren. Denn der Messwert wird mit "locate" auf die Position (hex0x8D) gesetzt. Die Legende "Messwert_1" bzw. "_2"ist einmal am Anfang per Tabelle ausgelesen worden. Und wird dann nicht mehr angetastet. Der eigentliche Messwert wird im Takt des ACs immer wieder überschrieben. Hier die 195. Sicher gibt es dafür bei der Laufschrift eine Lösung. Bin schon gespannt. ciao gustav
:
Bearbeitet durch User
Karl B. schrieb: > Das Display speichert einmal eingegebene Characters. Nö, du kannst da jeder Zeit wieder drüber schreiben. ;) Teo D. schrieb: > Nich vergessen das olle Zeugs kommt wieder. Ein RINGSpeicher, du weißt doch wann das wieder in Sicht kommt, ÜBERSCHREIBEN (wenns den sein muss), Leerzeichen sind auch erlaubt. Du kannst jedes Zeichen einzeln schreiben und scrollen o. in dir genehme Blöcke teilen, den gesamten (nicht sichtbaren) Speicher nutzen......
Teo D. schrieb: > Karl B. schrieb: >> Das Display speichert einmal eingegebene Characters. Sorry, missverständlich formuliert. Hoffte, es geht aus dem Nachsatz hervor. Der Controller nimmt einem die ganzen Locate-Befehle ja von vorne herein ab. Das kann man im Entry-Mode Set Shift Set ja einstellen, ob man nun Adressen- Increment oder -decrement haben möchte. Wenn ich jetzt eine ganz bestimmte Stelle und Zeile ansprechen möchte, werden die anderen Zeichen, die ich davor irgendwann einmal woanders auf dem Display eingegeben habe, nicht berührt. Es sei denn ich positioniere auf dieselbe Stelle. Bei der Laufschrift bleibt bei einer aktiven Positionierung alles, was z.B. links davon stand, stehen, wird nicht automatisch gelöscht. Deswegen ja auch die fatale Idee mit dem Display Clear. Die ja des Flimmerns wegen verworfen wurde. So sollte das "Speichern" verstanden werden. Die "Quick-and-Dirty"-Lösung oben löst dieses Problem, indem sie ständig von Position hex 0x80 (Anfang Zeile 1) positioniert. Somit bei Adressenincrement alles von links nach rechts überschreibt. ciao gustav
:
Bearbeitet durch User
Karl B. schrieb: > z.B. links davon stand, stehen, wird nicht automatisch gelöscht. Irgend wie kommen wie da nich zusammen???? Links ist das Display, also das was gerade angezeigt wird, das willst du doch nich wirklich löschen? Du schiebst ja alles von Rechts rein und wenn's nur Leerzeichen sind. Wenn du immer den selben Text durch scrollen willst, einfach die unerwünschte Lücke überspringen, scrollen was das LCD hergibt (also ohne Pause).
Ok, erst einmal ohne den Entry-Mode-Shift-Set zu verstellen. (Das geht natürlich - wenn es richtig gemacht wird - von Hause aus schon.) Wollte nur noch einmal kurz darauf eingehen: Karl B. schrieb: > Der Controller nimmt einem die ganzen Locate-Befehle ja von vorne herein > ab. > Das kann man im Entry-Mode Set Shift Set ja einstellen, ob man nun > Adressen-Increment oder -Decrement haben möchte. Das heißt aber nicht, dass es einem verboten ist, selber Zeichen an die gewünschte Position im Display-RAM zu setzen (auch in den nicht sichtbaren Bereich) - mit der Locate-Anweisung, die die entsprechende Adresse enthält. Nehmen wir einmal folgenden Fall: Jetzt steht durch eine vorherige Eingabe ein Text von Anfang Zeile 1 bis Spalte 3 Zeile 1. Setze ich jetzt einen Positionierungsbefehl auf hex 0x8D, dann wird das darauf folgende Byte im Charakter-Schreib-Mode genau dahin geschrieben, ohne, dass die drei Zeichen am Anfang der Zeile verschwunden sind. Das ist dann die manuelle Positionierung, der dann das Adressenincrement ab der bewusst gesetzten Position folgt. Also ohne extra Locate-Anweisung wird das folgende Byte auf Spalte hex 0x8E geschrieben. etc. So verstehe ich das. Wird jetzt gescrollt bzw. geshiftet, wird entweder der gesamte Displayinhalt rechts- oder links versetzt, oder sogar der Text spiegelverkehrt geschrieben. Das ist im Prog. nicht der Fall. Das wäre eine andere Lösung. Bis bald. ciao gustav
:
Bearbeitet durch User
Karl B. schrieb: > ... > So verstehe ich das. Richtig. Karl B. schrieb: > Wird jetzt gescrollt bzw. geshiftet, wird entweder der gesamte > Displayinhalt rechts- oder links versetzt Klar. Karl B. schrieb: > oder sogar der Text > spiegelverkehrt geschrieben. Was??? Niemals! Wie kommst du drauf. Karl B. schrieb: > Das ist im Prog. nicht der Fall. Was? ? ?? ??? Du willst o. kannst mich nich verstehen....
Hi, der code von Gustav funktioniert soweit für mich. @gustav: Danke für die Mühe. Allerdings habe ich immer noch ein verständnisproblem warum mein code im Eingangspost nicht funktioniert. Kann das vielleicht nochmal einer erklären? Vielen dank alle Grüße Der Tobi
Teo D. schrieb: > Karl B. schrieb: >> oder sogar der Text >> spiegelverkehrt geschrieben. Sorry, von rechts nach links , natürlich nicht die Buchstaben als solche spiegelverkehrt. Cursor move von rechts nach links -> Adressendecrement. Beispiel hier: Siehe Bild Tobi schrieb: > Allerdings habe ich immer noch ein verständnisproblem warum mein code im > Eingangspost nicht funktioniert. > Kann das vielleicht nochmal einer erklären? Hi, das ist die Organisation des DDRAMS, die für die meisten LCDs des HD44780- Controllers, egal, wieviel Spalen sie haben, gilt. Sind weniger Spalten da, als ( ähhm afaik ) 80 zählt der Adresscounter ins "Nirvana", wird er einfach weitergezählt. Daher die Software-Akrobatik. Besser wäre es, wenn Hitachi für jede LCD-Größe einen extra passenden Controller eingebaut hätte.. ciao gustav
:
Bearbeitet durch User
Karl B. schrieb: > Sorry, > von rechts nach links , natürlich nicht die Buchstaben als solche > spiegelverkehrt. Man, bin aus allen Wolken gefallen. Denk an meine Gesundheit und schock mich nicht so. ;) Wollt doch nur helfen, hab durch Missverständnisse scheinbar nur Verwirrung gestiftet -> Ein Koch zu viel, ich halt mich mal rau.
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.