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