Forum: Mikrocontroller und Digitale Elektronik Und wieder ein LCD Problem (Schwarze Kasten)


von cpehonk (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,
ich brauche auch noch mal Rat & Tat bei dem Thema LCD:
Habe an einem at89C52 ein LCD (162A von Reichelt, KS 0070B) 
angeschlossen und will es im 4-Bit Modus betreiben. Den Quellkode habe 
ich beigefügt.
"SetDigit" gibt einfach an Port 1 für ein Doppel-7-Segment eine Zahl aus 
(Debugging light).
Verbunden sind:
AT89C52         LCD
P0.4            DB4
P0.5            DB5
P0.6            DB6
P0.7            DB7

P0.3            RS
P0.2            E

                R/W, DB0-DB3 auf GND
                Vdd = +5V, Vee über 10K Poti zwischen +5V und GND

Timing erzeuge ich via 16-Bit Timer 0.
Aber ich bekomme anscheinend die Initialisierung nicht hin. Sehe nach 
wie vor nur eine komplette Zeile schwarzer Kästchen. Habe gelesen, dies 
weise auf die fehlende Initialisierung hin. Was aber ist hier falsch ?

Bin für Euren Rat dankbar !!

Viele Grüße
Christoph

von Gast (Gast)


Lesenswert?

Nicht Initialisiert, oder es ist kaputt.

von Klaus W. (mfgkw)


Lesenswert?

VSS (Pin 1) muß auch noch auf GND

von cpehonk (Gast)


Lesenswert?

Ja, Pin 1 des LCD ist auch an GND gelegt. Sorry, hatte ich nicht dazu 
geschrieben.
Da ich sowohl mit einem 161A als auch mit einem 162A nur die schwarzen 
Felder sehe, ist das Ding sicherlich nicht kaputt, sondern nicht 
initialisiert. Aber da liegt ja auch mein Problem. Laut Datenblatt alles 
richtig - nur funktionieren will es nicht. Vielleicht seht Ihr ja den 
Fehler ...

Viele Grüße
Christoph

von Karl H. (kbuchegg)


Lesenswert?

Wenn die Sequenz stimmt, würde ich einfach mal alle Zeiten mal 10 
nehmen. Wenn du zu langsam bist, langweilt sich das LCD, spielt aber 
ansonsten mit. Bist du aber zu schnell ....

von Gast (Gast)


Lesenswert?

Hast du nach jedem senden von Daten an das LCD auch das Enable Signal 
von High auf Low wechseln lassen? Ansonsten übernimmt er die Daten ja 
nicht.

von cpehonk (Gast)


Lesenswert?

Werde das mit den Zeiten mal ausprobieren. Ich gehe bei "Chip Enable" 
von Active-Hi aus, also lasse ich ansonsten das Signal auf "0" liegen.
Hier der C-Code Ausschnitt:

void LcdClock(unsigned char val)
{
  LCD_OUT = ( val & LCD_VALUE ) ;
  _nop_() ;
  _nop_()  ;
  LCD_OUT = ( val & LCD_VALUE ) | LCD_E ;
  _nop_() ;
  _nop_() ;
  _nop_() ;
  _nop_() ;
  LCD_OUT = ( val & LCD_VALUE ) ;
}

Habe einen Quarz von 12 MHz am C52, damit sollten also ca. 330 ns 
vergehen, bevor E wieder von Hi auf Lo geht. Lt. Datenblatt reicht eine 
Flankendauer von 220 ns aus.
Verflixte kleine Biester ...

Christoph

von Gast (Gast)


Lesenswert?

>Werde das mit den Zeiten mal ausprobieren. Ich gehe bei "Chip Enable"
>von Active-Hi aus, also lasse ich ansonsten das Signal auf "0" liegen.
>Hier der C-Code Ausschnitt:

Die Zeit für denn Wechsel von High nach low ist zu gering. Ich habe bei 
einem 4MHz Quarz 5us benötigt um eine korrekte Funktion zu ermöglichen. 
Erhöhe diese also mal Testweise auf 10us und gehe dann Stück für Stück 
runter

von cpehonk (Gast)


Lesenswert?

Tja, ...

Ich habe jetzt in die Lo -> Hi -> Lo Schleife für "E" ein Delay von mehr 
als 50µs gesetzt ... ohne Erfolg. Auch die anderen Timings habe ich 
verlängert. Alles ohne Erfolg.
Habe auch lange für das DCF77-Modul von Reichelt gebraucht, aber dank 
der Verstärkerschaltung funzt das wenigstens jetzt super.

Da muss beim LCD also noch ein anderer "dicker" Fehler sein ...

Viele Grüße
Christoph

von micha (Gast)


Lesenswert?

Es kann auch die Kontrastspannung falsch sein. Hast Du da ein Poti drin?
http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD

Eventuell ist auch der Duty-Cycle in der initalisierung falsch.

von cpehonk (Gast)


Lesenswert?

Die Kontrast-Spannung regle ich über das oben beschriebene 10K Poti.
Aber irgendwie will das Ding so gar nicht.

Duty-Cycle derzeit ist (E = Lo als Ausgangssituation):

delay 50 µs, dann Daten schreiben mit E = Hi, 50 µs warten, E = Lo

Muss man ggfs. einen bestimmten Port beim 89C52 verwenden ?
Ich nutze derzeit Port 0. Vielleicht reicht ja auch der Pin-Ausgang 
nicht ?

von schudi (Gast)


Lesenswert?

Hallo Christoph,

Port 0 ist meines wissens open Drain. Hast Du auch alle Pins mit Pull Up 
Widerständen beschaltet?

Grüße

Lothar

von Werner F. (frewer)


Lesenswert?

hallo,

an Deiner Stelle würde ich die Library von Fleury benutzen, die für das 
LCD einen kompletten Set von Routinen beinhaltet, die bestens 
funktionieren. Dann brauchst Du im Hauptprogramm nur noch LCD_init() 
aufrufen und alles ist gegessen. Davor natürlich sind die Vereinbarungen 
von Port und Pin in der zugehörigen Header-Datei einzustellen und 
natürlich die Osz-Frequenz. Bei Fleury ist alles drin mit der Ausnahme 
des Auslesens von Daten aus dem LCD-DRAM.
mfG
Werner

von holger (Gast)


Lesenswert?

>Bei Fleury ist alles drin mit der Ausnahme
>des Auslesens von Daten aus dem LCD-DRAM.

Was hat Fleury mit 89C52 zu tun? Richtig! Gar nichts.

von cpehonk (Gast)


Lesenswert?

Das mit dem Open-Drain ist ein guter Hinweis. Natürlich habe ich keine 
Pull-Ups davor. Wieviel K sollten es sein ? 10 K ?

Die Lib von Fleury habe ich mir angesehen und auch versucht, anzupassen. 
Ist aber, da nicht direkt (wie Holger geschrieben hat) für den C52 sehr 
mühsam.

Viele Grüße
Christoph

von Steffen K. (steffen3)


Lesenswert?

Als pull-up würde ich irgendwas zwischen 4k7 und 10k nehmen(ohne 
gewähr;-))

von cpehonk (Gast)


Lesenswert?

Habe es mal fix mit Port 2 versucht. War leider auch nicht besser.
(Ohne Pull-Ups). Der Fehler liegt wohl doch eher im Sourcecode begraben 
...

Viele Grüße
Christoph

von holger (Gast)


Lesenswert?

LCD_OUT = ( val & LCD_VALUE ) ;

Darüber solltest du noch mal ausgiebig nachdenken.
Was steht da im Endeffekt?

  LCD_OUT = ( val & 0xF8 ) ;

Bei val = 0x30 ist LCD_OUT auch 0x30.
Da du ja nur das Highnibble ausgibst könntest
du auch gleich schreiben:

  LCD_OUT = val ;

Wenn du LCD_RS setzen möchtest musst du das anders machen.
Kleiner Tip:
Port lesen in temp
Bits in temp ändern (Maskieren, löschen, verodern)
temp auf Port ausgeben

von cpehonk (Gast)


Angehängte Dateien:

Lesenswert?

Danke für den Tipp, Holger.

Hatte dies auch schon als Schwachpunkt entdeckt und die Funktionen neu 
geschrieben. Der geänderte Sourcecode ist im Anhang.
Geht aber immer noch nicht ... verfl... !!

Viele Grüße
Christoph

von Bernhard M. (boregard)


Lesenswert?

Hi,

du hast:
1
#define  LCD_VALUE  (0xF0 | LCD_RS | LCD_RW)
und dann
1
LCD_OUT = ( val & LCD_VALUE ) ;
wobei val z.B. 0x30 beim init ist.
Da wird aber dann LCD_RS und LCD_RW nie gesetzt, die werden ja durch das 
& wieder gelöscht...

Wie wäre es mit:
1
#define  LCD_VALUE(a)  ((a) & 0xF0) | LCD_RS | LCD_RW)
und dann entsprechend:
1
LCD_OUT = LCD_VALUE (val) ;

Das könnte eher gehen, oder?

Gruß,
Boregard

von Peter D. (peda)


Lesenswert?

Die meisten Probleme treten auf, weil die Leute versuchen, immer den 
ganzen Port zu setzen und sich dann in den AND/ORs verheddern.

Der 8051 hat wunderschöne Bitbefehle, damit gehts viel leichter:

http://www.mikrocontroller.net/attachment/30300/lcd_drv.zip

Dieses Beispiel läßt sich leicht auf den 8051 portieren.
Das Bitmacro braucht man nicht, der Keil C51 hat schon einen 
sbit-Befehl.
Also einfach diesen benutzen.
Die Directionbit braucht man auch nicht, also weglassen.
Nur das Delay-Macro muß man sich selber schreiben (kann man mit dem 
Timer machen).

Und P0 ohne pullups geht auf garkeinen Fall.


Peter

von cpehonk (Gast)


Lesenswert?

Hallo Boregard,

LCD_E wird in der "LcdClock" Routine entsprechend gesetzt ( "LCD_OUT = ( 
val & LCD_VALUE ) | LCD_E ; "). Die Werte für LCD_RS und LCD_RW (sofern 
benötigt), kommen in den LcdWriteChar() und LcdWriteCmd() Funktionen zum 
Einsatz (z.B. LcdWriteChar(): "LcdClock( ( dval & 0xF0 ) | LCD_RS ) ;").
Ich schaue mir das auch noch einmal an, aber per Debug schien es erstmal 
in Ordnung zu sein.

@Peter: Werde mal Dein angehängtes Archiv anschauen. Mit den 
Bit-Befehlen hast Du recht. Hatte nur erst einmal keine Lust, Assembler 
+ C zu mischen ...

Viele Grüße
Christoph

von cpehonk (Gast)


Lesenswert?

Hallo Peter,

habe die Files von Dir angepasst. Leider ohne Erfolg. Habe langsam das 
Gefühl, dass das Problem im Berechnen der Delays liegt. Hat jemand 
fertige Routinen für "_delay_us" oder "_delay_ms" für einen C52 mit 12 
MHz Quarz ?

Viele Grüße
Christoph

von cpehonk (Gast)


Lesenswert?

Zum Abschluss:

Bin zurück auf 8-Bit Breite gegangen und habe die Steuerleitungen auf 
einen anderen Port gelegt. Mit leicht modifiziertem Delay läuft das 
Display jetzt problemlos.

Danke nochmal an Alle, die gute Ratschläge parat hatten und mir geholfen 
haben.

Viele Grüße
Christoph

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.