Forum: Mikrocontroller und Digitale Elektronik LCD Lauftext Atmega8


von Tobi (Gast)


Angehängte Dateien:

Lesenswert?

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

von chris (Gast)


Lesenswert?

Warum so kompliziert ?? Das LCD anweisen es selber zu machen

von Tobi (Gast)


Lesenswert?

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.

von Uhrmacher (Gast)


Lesenswert?

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?

von Tobi (Gast)


Lesenswert?

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?

von Uhrmacher (Gast)


Lesenswert?

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

von spess53 (Gast)


Lesenswert?

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

von Diek (Gast)


Lesenswert?

Wieviele Zeichen hat das Display pro Zeile?
Füllt der Text alle Zeichen aus?

von Karl B. (gustav)


Lesenswert?

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
von Gerald B. (gerald_b)


Lesenswert?

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 ;-)

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

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
von Uhrmacher (Gast)


Lesenswert?

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.

von Karl B. (gustav)


Lesenswert?

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

von Uhrmacher (Gast)


Lesenswert?

Karl B. schrieb:
> OK,
> dem SRAM ist das egal,

Aber dem Auge des Betrachters nicht.

von Tobi (Gast)


Lesenswert?

Hallo zusammen,
werde heute abend eure Vorschläge probieren. Bin jetzt aber erstmal 
unterwegs.

Grüße
der Tobi

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Hi,
'mal eine Quick-and-dirty-Lösung (mit dem ATiny4313 - der lpm Z+ Befehl 
geht da.)

viel Spaß

ciao
gustav

von Uhrmacher (Gast)


Lesenswert?

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.

von Uhrmacher (Gast)


Lesenswert?

dööörtier hätt' ich es auch nicht hinbekommen.

von Wolfgang (Gast)


Lesenswert?

Karl B. schrieb:
> Und evtl. ein "Display Clear" hinter jedem Print.

Das dadurch verursachte Flackern auf dem Display versucht man gewöhnlich 
zu vermeiden.

von Karl B. (gustav)


Lesenswert?

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

von Teo D. (teoderix)


Lesenswert?

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.

von Karl B. (gustav)


Lesenswert?

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
von Teo D. (teoderix)


Lesenswert?

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

von Karl B. (gustav)


Lesenswert?

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
von Teo D. (teoderix)


Lesenswert?

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

von Karl B. (gustav)


Lesenswert?

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
von Teo D. (teoderix)


Lesenswert?

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

von Tobi (Gast)


Lesenswert?

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

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

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
von Teo D. (teoderix)


Lesenswert?

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