Forum: Mikrocontroller und Digitale Elektronik LCD Problem im 4-Bit Modus


von Kai W. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe das Display (Datenblatt als Attachement) im 4-Bit Modus 
angeschlossen und den Initprozess dafür wohl auch richtig implementiert. 
Wenn ich nun versuche ein Zeichen auf das Display zu schreiben (Funktion 
sendCharacter), bekomme ich zwar ein Zeichen angezeigt, aber nicht das 
was ich angebe.
Im 8-Bit Modus funktioniert sendCharacter einwandfrei. Muss man wie bei 
den Kommandos auch bei den Zeichen im 4-Bit Modus eine andere Art der 
Übertragung implementieren als im 8-Bit Modus?
Im Quellcode habe ich den Buchstaben K angegeben. Auf dem Display 
erscheint aber ein $. Das Tutorial hier über LCDs habe ich mir schon 
durchgelesen. Ich verstehe aber einfach nicht wo das Problem liegt.

Könnt ihr mir weiterhelfen?


Gruß
Kai

von Cyblord -. (cyblord)


Lesenswert?

Kai Wierzoch schrieb:

> Muss man wie bei
> den Kommandos auch bei den Zeichen im 4-Bit Modus eine andere Art der
> Übertragung implementieren als im 8-Bit Modus?

Naja also du musst ein 8-Bit Zeichen im 4-Bit Modus natürlich in 2x4 Bit 
zerlegen und nacheinander senden. So wie alle Kommandos auch. Aber das 
sollte ja klar sein.
Ansonsten unterscheidet sich das Senden von Zeichen nicht vom 8-Bit 
Modus.

gruß cyblord

von Kai W. (Gast)


Lesenswert?

Wie sende ich den ein K in 2x4Bit? Muss ich erst die Hexzahl 0x4B (K) 
in 0b01001011 umwandeln und dann senden?

von Cyblord -. (cyblord)


Lesenswert?

Kai Wierzoch schrieb:
> Wie sende ich den ein K in 2x4Bit? Muss ich erst die Hexzahl 0x4B (K)
> in 0b01001011 umwandeln und dann senden?

Also die Zahlendarstellung ist dein Privatvergnügen. Da musst du deine 
Gedanken mal bisschen ordnen. Alle Kommunikation mit dem Display erfolgt 
via 4-Bit Bus also gibts da nur Bits.

Alle Daten (Zeichen und Kommandos) haben ja 8 Bit. Normalerweise werden 
die an D0-D7 angelegt und ein Strobe auf Enable ausgelöst.
Im 4-Bit Modus werden zuerst die unteren 4 Bits (Nibble) angelegt, dann 
Enable gestrobed, dann die oberen 4 Bit, und nochmal Strobe auf Enable.


gruß cyblord

von Lötlackl *. (pappnase) Benutzerseite


Lesenswert?

Kai Wierzoch schrieb:
> Wie sende ich den ein K in 2x4Bit? Muss ich erst die Hexzahl 0x4B (K)
> in 0b01001011 umwandeln und dann senden?

Da muß nix gewandelt werden, ist doch nur eine andere Darstellung 
desselben.
Stattdessen muß das Byte zerlegt und dem LCD in 2 Häppchen (high-nibble 
und low-nibble) angeboten werden.

mfg

von Cyblord -. (cyblord)


Lesenswert?

1
void sendCommand(unsigned char command)
2
{
3
  checkBusy();
4
  LCDPORT = command;
5
  LCDPORT &= ~ ((1<<RW)|(1<<RS));
6
  nopAbit();
7
  LCDPORT = 0;
8
}
9
10
void sendCharacter(unsigned char character)
11
{
12
  checkBusy();
13
  LCDPORT = character;
14
  LCDPORT &= ~ (1<<RW);
15
  LCDPORT |= (1<<RS);
16
  nopAbit();
17
  LCDPORT = 0;
18
}

Das geht natürlich so nicht. Hier werden ja die 8 Bit direkt auf den 
Port gelegt. Wie soll das gehen wenn du nur 4 Portleitungen verbunden 
hast? Das sollte aber eigentlich einleuchten.

gruß cyblord

von Kai W. (Gast)


Lesenswert?

cyblord ---- schrieb:
> Das geht natürlich so nicht. Hier werden ja die 8 Bit direkt auf den
>
> Port gelegt. Wie soll das gehen wenn du nur 4 Portleitungen verbunden
>
> hast? Das sollte aber eigentlich einleuchten.

Genau da liegt mein Problem. Wie übertrage ich denn z.B. den Buchstaben 
K im 4-Bit Modus? Ich muss erst das high-nibble und dann das low-nibble 
übertragen, aber wie?

von Andreas W. (geier99)


Lesenswert?

cyblord ---- schrieb:
> Im 4-Bit Modus werden zuerst die unteren 4 Bits (Nibble) angelegt, dann
> Enable gestrobed, dann die oberen 4 Bit, und nochmal Strobe auf Enable.

Ich habe jetzt nicht ins Datenblatt geschaut, aber bei meinen LCD-Modul 
übertrage ich immer zuerst das High und dann das Low Nibble.
Hmm, kocht da wieder jeder Hersteller sein eigenes Süppchen? :-)

von Michael (Gast)


Lesenswert?

Kai Wierzoch schrieb:
> Ich muss erst das high-nibble und dann das low-nibble
> übertragen, aber wie?

Indem du erst "character" überträgst (dabei kommt nur das high-nibble 
beim LCD an, weil nur D4..D7 benutzt werden), dann dein character 4-mal 
nach links schiebst, so dass das low-nibble in den oberen 4 Bit liegt, 
und dies dann auch zum LCD überträgst.

von Spess53 (Gast)


Lesenswert?

Hi

>Hmm, kocht da wieder jeder Hersteller sein eigenes Süppchen? :-)

Eigentlich nicht. Mir ist noch kein Controller untergekommen, der nicht 
die Reihenfolge High-Nibble - Low-Nibble hatte.

MfG Spess

von Kai W. (Gast)


Lesenswert?

Michael schrieb:
> Indem du erst "character" überträgst (dabei kommt nur das high-nibble
>
> beim LCD an, weil nur D4..D7 benutzt werden), dann dein character 4-mal
>
> nach links schiebst, so dass das low-nibble in den oberen 4 Bit liegt,
>
> und dies dann auch zum LCD überträgst.


Ich habe die Funktion wie folgt abgeändert. Jetzt bekomme ich statt 
eines $-Zeichens ein / angezeigt.
1
void sendCharacter(unsigned char character)
2
{
3
  checkBusy();
4
  LCDPORT |= character;
5
  LCDPORT |= character<<4;
6
  _delay_ms(250);
7
  LCDPORT &= ~ (1<<RW);
8
  LCDPORT |= (1<<RS);
9
  nopAbit();
10
  LCDPORT = 0;
11
}

Das mit dem <<4 habe ich aus dem Tutorial hier auf mikrocontroller.net.
Was mache ich falsch?

von Cyblord -. (cyblord)


Lesenswert?

Kai Wierzoch schrieb:

> Das mit dem <<4 habe ich aus dem Tutorial hier auf mikrocontroller.net.
> Was mache ich falsch?

Du machst irgendwas stupide nach ohne zu verstehen was du tun sollst. 
Schau erstmal wo du die 4 Leitungen am Controller genau angeschlossen 
hast. Beim LCD müssen die laut deinem DB an DB0-DB3 was eigentlich 
ungewögnlich ist, bei meinem müssen die immer an DB4-DB7. Aber du musst 
es für dein LCD halt richtig machen.
Dann kannst du entscheiden in welche Richtung zu shiften musst.

gruß cyblord

von (prx) A. K. (prx)


Lesenswert?

cyblord ---- schrieb:
> Beim LCD müssen die laut deinem DB an DB0-DB3

Wie kommst du da drauf? Das "... not used ..." übersehen?

von (prx) A. K. (prx)


Lesenswert?

Es gibt übrigens schier unendlich viele Implementierungen mit solchen 
Allerwelt-LCDs, auch im 4-Bit Modus. Beispielsweise die von Peter 
Fleury. Einfach danach suchen und nutzen.

von Cyblord -. (cyblord)


Lesenswert?

A. K. schrieb:
> cyblord ---- schrieb:
>> Beim LCD müssen die laut deinem DB an DB0-DB3
>
> Wie kommst du da drauf? Das "... not used ..." übersehen?

Jap stimmt. Hab ich in der Hektik falsch gelesen.

von Michael (Gast)


Lesenswert?

Kai Wierzoch schrieb:
> Was mache ich falsch?

Du maskierst das Low-Nibble in das High-Nibble. Damit der LCD-Controller 
irgendetwas mitbekommt, mußt du das verschobene Byte aber dorthin 
übertragen.

von Kai W. (Gast)


Lesenswert?

Michael schrieb:
> Kai Wierzoch schrieb:
>> Was mache ich falsch?
>
> Du maskierst das Low-Nibble in das High-Nibble. Damit der LCD-Controller
> irgendetwas mitbekommt, mußt du das verschobene Byte aber dorthin
> übertragen.

Wie übertrage ich denn das verschobene Byte?
Ich dachte, dass ich das mit der o.g. Änderung
Der Funktion bereits mache.

von Jobst M. (jobstens-de)


Lesenswert?

Kai Wierzoch schrieb:
> Wie übertrage ich denn das verschobene Byte?

Schon mal eine LED zum blinken gebracht?



Gruß

Jobst

von Cyblord -. (cyblord)


Lesenswert?

Kai Wierzoch schrieb:
> Wie übertrage ich denn das verschobene Byte?
> Ich dachte, dass ich das mit der o.g. Änderung
> Der Funktion bereits mache.

Hatte ich dir bereits geschrieben. Du musst für jedes Nibble (4-Bit) 
einen separaten Impuls auf die Enable Leitung geben.

> Schon mal eine LED zum blinken gebracht?
Frage ich mich auch. Eigentlich dachte ich am Anfang du hättest etwas 
Ahnung aber inzwischen scheint es du hast einfach stupide einen Code 
kopiert und dann willst du ohne jegliches Verständnis davon kurz mal auf 
4-Bit Modus umschalten. Dann kopier doch bitte gleich nen Code für 
4-Bit.

von Kai W. (Gast)


Lesenswert?

Stimmt. Ich habe nicht viel Ahnung von uC Programmierung. Ich bin erst 
seit ca. 1 Monat dabei. Eine LED habe ich schon zum Blinken gebracht. Da 
musste ich aber nicht auf Taktzyklen achten und Enable Bit setzen usw. 
usw. Natürlich kann ich eine fertige 4-Bit Code Lösung nehmen. Ich 
dachte nur, wenn ich selber programmiere, kapiere ich es eher und habe 
dann das Verständnis dafür. Da habe ich wohl falsch gedacht. 
Schuldigung.
Werde Euch nicht mehr nerven.


cyblord ---- schrieb:
> Hatte ich dir bereits geschrieben. Du musst für jedes Nibble (4-Bit)
>
> einen separaten Impuls auf die Enable Leitung geben.

Werde ich umsetzen. Vielen Dank.


Gruß
Kai

von (prx) A. K. (prx)


Lesenswert?

Kai Wierzoch schrieb:
> dachte nur, wenn ich selber programmiere, kapiere ich es eher und habe
> dann das Verständnis dafür.

Kann man machen. Andererseits kann man an funktionierendem Code anderer 
Leute manchmal auch erkennen, was man selber falsch gemacht hat.

von Cyblord -. (cyblord)


Lesenswert?

Kai Wierzoch schrieb:
> Ich
> dachte nur, wenn ich selber programmiere, kapiere ich es eher und habe
> dann das Verständnis dafür.

Guter Ansatz, aber es sieht nicht danach aus als hättest du den Code 
bisher verstanden, also gehe ich nicht davon aus dass du den selbst 
programmiert hast.

Denn wenn du das Prinzip der LCD Ansteuerung verstanden hättest, dann 
wüsstest du dass jeder Befehl und jedes Zeichen erst an den Bus angelegt 
und dann mit der Enable-Leitung reingetaktet wird. Und dann wäre dir 
auch klar dass man nicht einfach 2x 4 Bit anlegen kann, und dabei nur 
ein mal Enable taktet. Wer das macht der zeigt doch dass er gar nicht 
kapiert was da abläuft.

Falls du den Code wirklich selber schreiben willst, such dir mal ein 
besseres Datenblatt, deins ist nicht sooo gut und schau dir den im Netz 
die üppig vorhandenen Beispielcodes zu 4-Bit an.

Hier steht auch noch was dazu: 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung

gruß cyblord

von Jobst M. (jobstens-de)


Lesenswert?

Das war nicht böse gemeint. Nur wenn mich jemand fragt, wie man die 
Daten überträgt, dann frage ich mich, ob derjenige überhaupt schon mal 
Signale aus einem Controller ausgegeben hat. Also: Nicht eingeschnappt 
sein! Wir haben hier ganz andere Kandidaten :-)


Während Du im 8 Bit Modus immer ein ganzes Byte überträgst, musst Du im
4 Bit Modus die selben 8 Bit in zwei Häppchen a 4 Bit übertragen. So:
1
                _         _
2
E      ________/ \_______/ \__
3
4
       ___ ___________________
5
RS     ___X___________________  1 = Daten ; 0 = Befehle
6
7
       ___ _________ _________
8
DB4-7  ___X__D4-D7__X__D0-D3__
9
10
          |     |   |     |
11
          A     B   C     D

Du setzt also RS auf den richtigen Pegel und legst die oberen 4 Bit von 
Deinen 8 Bit an die 4 Datenleitungen (A). Dann wird ein Impuls auf die 
Enable-Leitung gelegt (B). Danach muß ein wenig gewartet werden (ca. 
40µs +/- je nach Display) und dann werden die unteren 4 Bit auf den 
Ausgang gegeben (C). Noch ein Puls auf Enable (D) und nochmal warten.

Ganz wichtig ist, daß Du dabei nicht durcheinander kommst, denn das 
Display erwartet immer 2 Nibbles (Halbbytes). Wenn Du also mal nur 1 
oder gar 3 lieferst, geht Dir die Kommunikation flöten.
Ist sie erst einmal flöten gegangen, hast Du von Deiner Seite keine 
Möglichkeit dies festzustellen. Wenn Du Dir unsicher bist, kannst Du das 
Display in regelmässigen Abständen initialisieren. Aber die saubere 
Variante ist das nicht.


Ach ja: In der Initialisierungsphase bei der Umschaltung von 8 zu 4 Bit 
werden NUR die 4 oberen Bits zum Display geschickt! Erst wenn zu 4 Bit 
umgeschaltet wurde, werden beide Nibble gesendet.



Gruß

Jobst

von Kai W. (Gast)


Lesenswert?

Ich bin nicht eingeschnappt. Ich bin nur etwas mit der ganzen Display 
Sache überfordert. Mir ist es ja auch peinlich ständig nachfragen zu 
müssen. Das mit dem 8-Bit Modus habe ich ja hinbekommen. Nur der 4-Bit 
Modus macht mich noch fertig. Danke für die Antwort. Ich versuche das 
mal programmatisch umzusetzen.


Gruß
Kai

von spess53 (Gast)


Lesenswert?

Hi

>Das mit dem 8-Bit Modus habe ich ja hinbekommen. Nur der 4-Bit
>Modus macht mich noch fertig.

Was mich verwundert ist, das du die Initialisierung hinbekommen hast (?) 
und jetzt an der Ausgabe von einzelnen Zeichen scheiterst. Von RS 
abgesehen werden die letzten Befehle der Initialisierung genau wie 
Zeichen ausgegeben.

Zeig mal deinen kompletten Code.

Mfg Spess

von Karl H. (kbuchegg)


Lesenswert?

Kai Wierzoch schrieb:
> Ich bin nicht eingeschnappt. Ich bin nur etwas mit der ganzen Display
> Sache überfordert. Mir ist es ja auch peinlich ständig nachfragen zu
> müssen. Das mit dem 8-Bit Modus habe ich ja hinbekommen. Nur der 4-Bit
> Modus macht mich noch fertig. Danke für die Antwort.

Auch dann ist es nicht verboten, mal anderen Code zu studieren.
Gerade wenn du den 8-Bit Mode alleine hingekriegt hast, wofür 
interessanterweise sogar einiges spricht, wenn man sich die Fehler in 
deinem Code ansieht, ist es keine Schande sich in anderem Code mal die 
Unterschiede anzusehen und diesen Code zu studieren.
Ganz im Gegenteil, die Fähigkeit fremden Code zu analysieren ist eine 
wichtige Fähigkeit, die jeder Programmierer lernen muss. Also warum 
nicht hier damit anfangen?

von Teo D. (teoderix)


Lesenswert?

spess53 schrieb:
> Was mich verwundert ist, das du die Initialisierung hinbekommen hast (?)
> und jetzt an der Ausgabe von einzelnen Zeichen scheiterst.

Weil nur der obere Nibble benutzt wird, so klappt das auch wenn man 
keinen Plan vom 4Bit-Modus hat.

von Kai W. (Gast)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Das mit dem 8-Bit Modus habe ich ja hinbekommen. Nur der 4-Bit
>>Modus macht mich noch fertig.
>
> Was mich verwundert ist, das du die Initialisierung hinbekommen hast (?)
> und jetzt an der Ausgabe von einzelnen Zeichen scheiterst. Von RS
> abgesehen werden die letzten Befehle der Initialisierung genau wie
> Zeichen ausgegeben.
>
> Zeig mal deinen kompletten Code.
>
> Mfg Spess

Der Code ist am Thread angehängt. s.o. Warum ich gerade daran verzweifel 
weiß ich auch nicht. Aber wahrscheinlich habe ich wirklich keinen Plan. 
Ich hoffe aber, dass ich ihn noch bekomme, wenn es mal funktioniert.

von Bastler (Gast)


Lesenswert?

RS auf "High"
oberes Nibble anlegen
Enablepuls
unteres Nibble anlegen
Enablepuls

Fertig!

von Karl H. (kbuchegg)


Lesenswert?

Kai Wierzoch schrieb:

> Der Code ist am Thread angehängt. s.o. Warum ich gerade daran verzweifel
> weiß ich auch nicht. Aber wahrscheinlich habe ich wirklich keinen Plan.
> Ich hoffe aber, dass ich ihn noch bekomme, wenn es mal funktioniert.

Das Problem in deinem Code ist zum Bleistift das hier
1
    sendCommand(0b00000000);//Start: Display on/off
2
    sendCommand(0b11110000);//Display: on, Cursor: on, Cursor: blinkender Block

in Kombination mit
1
void sendCommand(unsigned char command)
2
{
3
  checkBusy();
4
  LCDPORT = command;
5
  LCDPORT &= ~ ((1<<RW)|(1<<RS));
6
  nopAbit();
7
  LCDPORT = 0;
8
}

Das was du mit dem doppelten Aufruf von sendCommand machst, sollte in 
Wirklichkeit die Funktion selber machen.
Du übergibst der Funktion ein Byte und die Funktion selbst zerlegt sich 
das in 2 Stück 4-Bit Einheiten und bringt die auf den Weg. Es ist 
sinnlos, wenn du dieses Detail dem Aufrufer von sendCommand aufbrummst.

Wie gesagt: Such dir anderen LCD-Code, der mit 4-Bit Ansteuerung umgehen 
kann und studiere, wie es dort gemacht wurde. Du willst es doch nach 
eigenen Aussagen lernen. Zum Lernen gehört genau das: Auch mal 
nachsehen, wie andere das machen. Davon kann man eine Menge lernen. Und 
zwar ohne dass dir hier im Forum die Antworter alles wieder von vorne 
vorkauen müssen.

von Kai W. (Gast)


Lesenswert?

Wollte nur bescheid geben, dass es funktioniert.
Ich habe ein Beispielcode für 4-Bit Modus gefunden.

Vielen Dank für euere Hilfe,

Gruß
Kai

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.