Forum: Mikrocontroller und Digitale Elektronik bockiges LCD


von Egon M. (kpc)


Lesenswert?

Hallo,

ich versuche verzweifelt, zwei neu bei Reichelt gekaufte LCD's
anzusteuern, aber mehr als eine Zeile schwarzer Kästchen kann ich nicht
produzieren. Setze ich dagegen in die Halterung einen älteren LCD ein, 
dann funktioniert alles bestens.

Ich vermute, meine Initialisierungsroutine ist falsch. Sie wurde aber
haarklein aus dem Datenblatt übernommen (und später noch vielfältig 
variiert).

Datenblatt und Bauteil stimmen überein: LCD 162C BCBC steht auf beiden.
Das ältere, funktionierende, LCD ist vom gleichen Typ.

Meine Initialisierungsroutine sieht so aus:
1
int lcd_init(void)      
2
  {
3
  DDRC |= (1<<RS) | (1<<E);     // RS=PC2=4 und E=PC3=8 sind Ausgänge 
4
  kdo(60);  kdo(60); kdo(60); kdo(60);   // function set, vier mal
5
  kdo(1);     // Display clear
6
  kdo(15);    // Display on/off: 8 + 4 (Display on) + 2 (Curs home) + 1 (blinking on)
7
  kdo(6);     // entry mode: 4 + 2 (cursor increase) + 0 (Display not shifted)
8
  kdo(20);  // shift: 16 + 0 (cursor move) + 4 (right shift)
9
   return 0;   // lt. Datenblatt: 48+x (4mal), dann 8 - 1 - 5, ist nicht besser
10
  }
Die Funktion kdo() beginnt mit _delay_ms(10), das sollte beim LCD sogar 
zum Kaffeetrinken ausreichen.

Das Ergebnis: statt der anzuzeigenden Texte oder Zahlen sieht man eine 
ganze Zeile schwarzer Kästchen. An der Kontrasteinstellung liegt das 
nicht, ist durchgetestet.

Kann mir jemand einen guten Rat geben, wie man das in Ordnung bringen 
kann?

Gruß
Egon

von Mike R. (thesealion)


Lesenswert?

Nur mal ein Tipp auf die Schnelle, die schwarzen Kästchen deuten auf 
eine fehlerhafte Initialisierung hin.
Was da genau schief läuft kann ich leider nicht sagen, dafür kenn ich 
mich mit diesen Displays gerade nicht mehr aus.

von spess53 (Gast)


Lesenswert?

Hi

>Die Funktion kdo() beginnt mit _delay_ms(10), das sollte beim LCD sogar
>zum Kaffeetrinken ausreichen.

Lt. Datenblatt braucht der Controller des Displays erst mal 30ms 
Wartezeit.

>kdo(60);  kdo(60);...

Dezimalzahlen an dieser Stelle sind so etwa das abwegigste was ich 
kenne.

MfG Spess

von Egon M. (kpc)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Die Funktion kdo() beginnt mit _delay_ms(10), das sollte beim LCD sogar
>>zum Kaffeetrinken ausreichen.
>
> Lt. Datenblatt braucht der Controller des Displays erst mal 30ms
> Wartezeit.
>
Genauer gesagt, 15 ms. Ist bei mir durch andere Programmschritte mit 
1000ms mehr als erfüllt.

>>kdo(60);  kdo(60);...
>
> Dezimalzahlen an dieser Stelle sind so etwa das abwegigste was ich
> kenne.
>
Lassen sich bequem aus Bitwerten zusammenzählen, immerhin noch besser 
als Hex-Werte, die man oft in Manuals sieht.

mfg
Egon

von holger (Gast)


Lesenswert?

>Lassen sich bequem aus Bitwerten zusammenzählen, immerhin noch besser
>als Hex-Werte, die man oft in Manuals sieht.

Bei HEX Werten sieht der erfahrene Programmierer aber
schnell welche Bits gesetzt sind. Bei dezimal muß der
Taschenrechner ausgepackt werden.

von (prx) A. K. (prx)


Lesenswert?

Egon Müller schrieb:

> Lassen sich bequem aus Bitwerten zusammenzählen, immerhin noch besser
> als Hex-Werte, die man oft in Manuals sieht.

Ne im Ernst? Du zerlegst 159 im Kopf schneller in einzelne Bits als 
0x73?

von Egon M. (kpc)


Lesenswert?

holger schrieb:
>>Lassen sich bequem aus Bitwerten zusammenzählen, immerhin noch besser
>>als Hex-Werte, die man oft in Manuals sieht.
>
> Bei HEX Werten sieht der erfahrene Programmierer aber
> schnell welche Bits gesetzt sind. Bei dezimal muß der
> Taschenrechner ausgepackt werden.

Mag sein, ist vielleicht auch Gewöhnungssache.

Aber, was kann ich nun an meiner Initialsierungsroutine ändern?
Vorschläge werden gern in HEX entgegengenommen.

Viele Grüße
Egon

von (prx) A. K. (prx)


Lesenswert?

Egon Müller schrieb:

> Aber, was kann ich nun an meiner Initialsierungsroutine ändern?
> Vorschläge werden gern in HEX entgegengenommen.

Annersrüm läuft der Hase. Du erwartest doch wohl nicht, dass nun jeder 
seine tragbare Rechenfähigkeitserweiterung rauskramt um deine 
heissgeliebten Dezimalwerte in Hex umzurechnen. Wird für dich doch ein 
Klacks sein, das nochmal in Hex zu bringen.

von Michael U. (amiga)


Lesenswert?

Hallo,

viel interessanter fände ich den Source von kdo().
Interessant fände ich auch den Controllertyp, ich habe eigentlich keine 
Lust, jetzt bei Reuchekt nach irgendwelchen Datenblättern zu kramen.
Nach so Kleinigkeiten wie den AVR-Typ und vor allen die Taktfrequenz 
traue ich mich garnicht emhr zu fragen...

Gruß aus Berlin
Michael

von spess53 (Gast)


Lesenswert?

Hi

@Michael: Du wirst noch mal an Reizüberflutung sterben.

MfG Spess

von Egon M. (kpc)


Lesenswert?

A. K. schrieb:
> Egon Müller schrieb:

> heissgeliebten Dezimalwerte in Hex umzurechnen. Wird für dich doch ein
> Klacks sein, das nochmal in Hex zu bringen.

Nein, ist überhaupt kein Problem:
1
int lcd_init(void)      
2
  {
3
  DDRC |= (1<<RS) | (1<<E);     // RS=PC2=4 und E=PC3=8 sind Ausgänge 
4
  kdo(0x3C);  kdo((0x3C); kdo(3C); kdo(3C);   // function set, vier mal
5
  kdo(0x01);     // Display clear
6
  kdo(0x0E);    // Display on/off: 8 + 4 (Display on) + 2 (Curs home) + 1 (blinking on)
7
  kdo(0x06);     // entry mode: 4 + 2 (cursor increase) + 0 (Display not shifted)
8
  kdo(0x14);  // shift: 16 + 0 (cursor move) + 4 (right shift)
9
   return 0;   // lt. Datenblatt: 0x30+x (4mal), dann 0x08 - 0x01 - 0x05, ist nicht besser

Sooo schlecht finde ich die Rechnerei in HEX nun auch wieder nicht, ist 
halt Gewohnheitssache.

Gruß
Egon

von holger (Gast)


Lesenswert?

Mach aus den 0x3C mal 0x38. Und ein fettes
delay 100ms bevor du irgendwas in das Display schreibst.

von (prx) A. K. (prx)


Lesenswert?

kdo() fehlt immer noch.

von Egon M. (kpc)


Lesenswert?

Michael U. schrieb:
> Hallo,
>
> viel interessanter fände ich den Source von kdo().
> Interessant fände ich auch den Controllertyp, ich habe eigentlich keine
> Lust, jetzt bei Reuchekt nach irgendwelchen Datenblättern zu kramen.
> Nach so Kleinigkeiten wie den AVR-Typ und vor allen die Taktfrequenz
> traue ich mich garnicht emhr zu fragen...
>
> Gruß aus Berlin
> Michael

Entschuldigung, ich hatte gedacht, meine spärlichen Angaben würden das 
Problem hinreichend beschreiben (insbesondere, da das alte LCD vom 
gleichen Typ ja o.B. ist.
Also, es handelt sich um einen Atmega644, Taktfrequenz 16 MHz, 
Clockfrequenz des zwischengeschalteten PCF8574 100 kHz; Kontrollertyp 
lt. Datenblatt KS0070B.
Die Funktion kdo() ist, so hoffe ich, unauffällig:
1
 void kdo(uint8_t dat)          // ein Kommando zum LCD 
2
  {
3
    _delay_ms(10);
4
  PORTC &= ~(1<<RS);        // RS=0 (Daten ins Steuerregister)
5
  PORTC |= (1<<E);       // = E high  
6
    zumPCF(dat);           // legt ein Byte an die PCF-Ausgänge
7
  PORTC &= ~(1<<E);         // das Byte liegt jetzt am LCD-Eingang an 
8
  _delay_ms(5);         // pause()zu lang,    ns reichen 
9
  PORTC |= (1<<E);          // E wieder high 
10
  _delay_ms(5);
11
  return;
12
  }

Fehlt noch etwas an Informationen?

Gruß
Egon

von (prx) A. K. (prx)


Lesenswert?

Unauffällig schon, aber falsch. E ist verkorkst. Das ist ausnahmsweise 
mal bei 1 aktiv. Also:

Daten anlegen.
E rauf
1µs warten (keine 5ms, zu lang ist ungesund)
E runter

Ich nehme mal an, das Display ist 8bittig angeschlossen.

von holger (Gast)


Lesenswert?

Änder mal die Reihenfolge und Zeiten:
1
 void kdo(uint8_t dat)          // ein Kommando zum LCD 
2
  {
3
    _delay_ms(10);
4
  PORTC &= ~(1<<RS);        // RS=0 (Daten ins Steuerregister)
5
    zumPCF(dat);           // legt ein Byte an die PCF-Ausgänge
6
  PORTC |= (1<<E);       // = E high  
7
  _delay_us(2);         // pause()zu lang,    ns reichen 
8
  PORTC &= ~(1<<E);         // das Byte liegt jetzt am LCD-Eingang an 
9
  _delay_us(50);         // pause()zu lang,    ns reichen 
10
  return;
11
  }

von Egon M. (kpc)


Lesenswert?

holger schrieb:
> Mach aus den 0x3C mal 0x38. Und ein fettes
> delay 100ms bevor du irgendwas in das Display schreibst.

Hilft leider nicht.
Das andere, was Du weiter unten geschrieben hast, probiere ich gleich 
aus

Egon

von Egon M. (kpc)


Lesenswert?

holger schrieb:
> Änder mal die Reihenfolge und Zeiten:
>
>
1
>  void kdo(uint8_t dat)          // ein Kommando zum LCD
2
>   {
3
>     _delay_ms(10);
4
>   PORTC &= ~(1<<RS);        // RS=0 (Daten ins Steuerregister)
5
>     zumPCF(dat);           // legt ein Byte an die PCF-Ausgänge
6
>   PORTC |= (1<<E);       // = E high
7
>   _delay_us(2);         // pause()zu lang,    ns reichen
8
>   PORTC &= ~(1<<E);         // das Byte liegt jetzt am LCD-Eingang an
9
>   _delay_us(50);         // pause()zu lang,    ns reichen
10
>   return;
11
>   }
12
>

Hallo Holger
das Elend ist unverändert.
Deine Programmsequenz ist aber keineswegs falsch, ich habe nochmals das 
alte LCD eingesteckt und es funktioniert damit.

Ob das LCD einen Knacks hat? Ich hatte vor einiger Zeit eines von 
Reichelt gekauft, und weil es nicht funktionierte, mir vorgestern ein 
zweites kommen lassen. Ob es aus der gleichen (Montags)-Sserie ist?

Egon

von holger (Gast)


Lesenswert?

>Ob das LCD einen Knacks hat? Ich hatte vor einiger Zeit eines von
>Reichelt gekauft, und weil es nicht funktionierte, mir vorgestern ein
>zweites kommen lassen. Ob es aus der gleichen (Montags)-Sserie ist?

Das glaub ich nicht. Miss doch mal die Pegel am PCF.
Vieleicht kommen die Datenleitungen vom LCD nicht
weit genug auf High.

von (prx) A. K. (prx)


Lesenswert?

Wüsste nicht warum, die HD44780 Controller sind erstens keine Last und 
haben zweitens sogar selber noch Pullups drin.

von Egon M. (kpc)


Lesenswert?

holger schrieb:

> Das glaub ich nicht. Miss doch mal die Pegel am PCF.
> Vieleicht kommen die Datenleitungen vom LCD nicht
> weit genug auf High.

Es sind glatt und sauber 5V, sowohl an den Datenleitungen als auch
an RS und E.

Egon

von holger (Gast)


Lesenswert?

>Wüsste nicht warum, die HD44780 Controller sind erstens keine Last und
>haben zweitens sogar selber noch Pullups drin.

Man weiß ja nie so genau was da drin steckt;)

>Es sind glatt und sauber 5V, sowohl an den Datenleitungen als auch
>an RS und E.

Hast du noch das fette delay am Anfang drin und die 0x38?

Sonst fällt mir so langsam auch nichts mehr ein.

von holger (Gast)


Lesenswert?

Einen habe ich noch:

  kdo(1);     // Display clear
  kdo(15);    // Display on/off: 8 + 4 (Display on) + 2 (Curs home) + 1

Tausch die beiden Zeilen mal

  kdo(15);    // Display on/off: 8 + 4 (Display on) + 2 (Curs home) + 1
  kdo(1);     // Display clear

von R. F. (rfr)


Lesenswert?

Wenn das LCD ein Hochtemperaturdisplay ist, muss man irgendwas am 
Kontrast anders einstellen. Ich habe aber vergessen, was.

Deine Kontrasteinstellung hast du geprüft?

Gruss

R.

von Egon M. (kpc)


Lesenswert?

holger schrieb:

> Hast du noch das fette delay am Anfang drin und die 0x38?
>

Ja, die Reihenfolge ist:
 0x38 ( 4 mal ), 0x01, 0x0F, 0x06, 0x14.

Die 100ms sind jetzt vor jeden Aufruf, wo etwas geschrieben werden soll.

Dann habe ich noch getauscht zu 4x 0x038, 0x0F, 0x01, 0x06 und 0x14.

Leider ohne Erfolg.

Gruß
Egon

von Egon M. (kpc)


Lesenswert?

R. Freitag schrieb:
> Wenn das LCD ein Hochtemperaturdisplay ist, muss man irgendwas am
> Kontrast anders einstellen. Ich habe aber vergessen, was.
>
> Deine Kontrasteinstellung hast du geprüft?
>
> Gruss
>
> R.

Also, Hochtemperatur glaube ich nicht (auf der Rückseite steht die 
gleiche Bezeichnung wie beim alten).

Am Kontrast habe ich hin und her gedreht, weil ich irgendwo gelesen 
hatte, die dunklen Punkte könnten vielleicht die Zeichen überdecken - 
aber leider ist da nichts rauszuholen.

Schade

Gruß
Egon

von holger (Gast)


Lesenswert?

>Dann habe ich noch getauscht zu 4x 0x038, 0x0F, 0x01, 0x06 und 0x14.

Man könnte jetzt noch päpstlicher sein als der Papst und dem
KS0070 Datenblatt folgen, laut dem nur einmal 0x38 gesendet
werden muß. Aber ich denke das bringt auch nichts mehr.

Alle Lötstellen am Display noch einmal überprüfen.
End of Transmission :(

von Egon M. (kpc)


Lesenswert?

holger schrieb:
>>Dann habe ich noch getauscht zu 4x 0x038, 0x0F, 0x01, 0x06 und 0x14.
>
> Man könnte jetzt noch päpstlicher sein als der Papst und dem
> KS0070 Datenblatt folgen, laut dem nur einmal 0x38 gesendet
> werden muß. Aber ich denke das bringt auch nichts mehr.
>
Hat nichts gebracht.
Aus den Appnotes  usw. kannte ich es mit dreimaligem Aufruf, im 
Datenblatt zum 162C BCBC steht vier mal, das hatte ich übernommen.


> Alle Lötstellen am Display noch einmal überprüfen.
> End of Transmission :(

Das war der richtige Einfall!
Nachdem ich erst mal dachte, das kann doch nicht sein, das andere 
funktioniert doch auch - fielen mir die an jedes Teil anzulötenden 
Steckerleisten ein. Ich habe sie mir mit dem Mikroskop angesehen und 
fand eine Stelle, wo das Lot nur auf der Lötfläche, nicht am Pin war.

Peinlich, peinlich, ich weiß.

Nun funktioniert es endlich!

Vielen Dank, Holger, für Deine Hilfe!

(und den anderen Ratgebern natürlich auch!)

Viele Grüße
Egon

von spess53 (Gast)


Lesenswert?

Hi

>Hat nichts gebracht.
>Aus den Appnotes  usw. kannte ich es mit dreimaligem Aufruf, im
>Datenblatt zum 162C BCBC steht vier mal, das hatte ich übernommen.

Massgebend ist das Datenblatt des Controllers. Und dort steht nichts von 
viermal.

MfG Spess

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.