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
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
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 ....
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.
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
>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
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
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.
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 ?
Hallo Christoph, Port 0 ist meines wissens open Drain. Hast Du auch alle Pins mit Pull Up Widerständen beschaltet? Grüße Lothar
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
>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.
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
Als pull-up würde ich irgendwas zwischen 4k7 und 10k nehmen(ohne gewähr;-))
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
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
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
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
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
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.