Hallo,
ich habe ein Problem mit meinem LCD (4x20 Zeichen, DEM20485-SYH-LY), das
ich an einem ATmega8 angeschlossen habe.
Mein Testprogramm mit Initalisierung des LCDs und einer Zeichenausgabe
funktioniert. Jedoch funktioniert es nur direkt nach dem Programmieren,
oder nach mehrmaligem resetten des ATmega8 (wenn der programmer nicht
mehr angeschlossen ist).
Die Atmega-Beschaltung entspricht der aus dem AVR-Tutorial. Ich verwende
jedoch einen 4MHz Quarzoszillator (SUT_CKSEL fuse gesetzt auf
EXTCLK_6CK_64MS). Im Anhang noch ein Bild zur Beschaltung der Port-Pins.
Hatte jemand von euch schon einmal dieses Problem und könnte mir helfen?
Ich komme leider nicht weiter.
Bin für jeden Tipp dankbar.
Viele Grüße
fluppy
Hier ist noch das Programm:
1
#define F_CPU 4000000UL //definiere Takt-Konstante für delay.h
Nein.
Du musst 3 mal hintereinander die 0x30 anlegen. Direkt hintereinander
und mit Wartezeiten dazwischen. Und erst danach wird einmalig die 0x20
an den 4 oberen Bits angelegt und erst dann kommen die 0x28 für den
Modus, dann allerdings bereits mit der ganz normalen Ausgabefunktion für
8 Bit
Also
1
send_upper_4bit(0x30);//Function set 0x0011xxxx
2
_delay_ms(100);
3
send_upper_4bit(0x30);//Function set 0x0010xxxx
4
_delay_ms(100);
5
send_upper_4bit(0x30);//Function set 0x0010xxxx
6
_delay_ms(100);
7
8
send_upper_4bit(0x20);//Function set 0x0010xxxx
9
_delay_ms(100);
10
11
...understjetztistdasLCDzuverlässigim4BitModus
....
1
send_upper_4bit(0x00);//Display control 0x0000xxxx
Mann der Berge! Du hast doch Ausgabefunktionen für 8 Bit Werte
(send_instruction und send_data)! Warum benutzt du die denn nicht? Du
wirst doch im Hirn beklopft, wenn du selbst im Code die Codezahlen
entsprechend aufteilen musst! Das kann doch der Computer viel
zuverlässiger als du.
Hi
>Mein Testprogramm mit Initalisierung des LCDs und einer Zeichenausgabe>funktioniert. Jedoch funktioniert es nur direkt nach dem Programmieren,>oder nach mehrmaligem resetten des ATmega8 (wenn der programmer nicht>mehr angeschlossen ist).
Typisch, wenn die Wartezeit vor der LCD-Initialisierung zu kurz ist.
MfG Spess
spess53 schrieb:> Hi>>>Mein Testprogramm mit Initalisierung des LCDs und einer Zeichenausgabe>>funktioniert. Jedoch funktioniert es nur direkt nach dem Programmieren,>>oder nach mehrmaligem resetten des ATmega8 (wenn der programmer nicht>>mehr angeschlossen ist).>> Typisch, wenn die Wartezeit vor der LCD-Initialisierung zu kurz ist.
Hatte ich auch gedacht. Aber 1 Sekunde sollte auf jeden Fall reichen.
@Karl Heinz: Vielen Dank für deine Hinweise. Ich werde sie beachten.
Karl Heinz schrieb:> [...]> Nein.> Du musst 3 mal hintereinander die 0x30 anlegen. Direkt hintereinander> und mit Wartezeiten dazwischen. Und erst danach wird einmalig die 0x20> an den 4 oberen Bits angelegt und erst dann kommen die 0x28 für den> Modus, dann allerdings bereits mit der ganz normalen Ausgabefunktion für> 8 Bit>> [...]
Bei der Initialisierung habe ich mich jedoch am Datenblatt des
LCD-Controllers (ST7066U) orientiert. Im Anhang die Initialisierung im
4-Bit Modus (Quelle: Datenblatt ST7066U)
Soll ich die init-Funktion trotzdem so umschreiben, wie du beschrieben
hast?
Er fragt das LCD-Busy nicht ab (DB7)
"DB7 can be used as a busy flag. The address counter is updated 4us
after the busy flag is cleared"
In Schreibroutinen sollte man dies immer abfragen,
das war bei mir das Problem.
BattMan schrieb:> Er fragt das LCD-Busy nicht ab (DB7)> "DB7 can be used as a busy flag. The address counter is updated 4us> after the busy flag is cleared"
Bei seinen Zeiten ist das ziemlich egal.
Nach 100ms ist auf einem LCD alles fertig.
Felix H. schrieb:> Bei der Initialisierung habe ich mich jedoch am Datenblatt des> LCD-Controllers (ST7066U) orientiert. Im Anhang die Initialisierung im> 4-Bit Modus (Quelle: Datenblatt ST7066U)
Du hast recht, die ist tatsächlich dort so angegeben.
Funktional sollte es eigentlich aufs gleiche rauslaufen. Da hab ich mich
wohl davon leiten lassen, dass der Anfang der Initialisierung nicht so
aussieht, wie er normalerweise aussieht.
Die Initialisierung mit 3 mal hintereinander 0x30 ist ja nur dazu da,
dass man das LCD aus einem gerade begonnenen Kommando rausholt, sollte
der Prozessorreset just zu einem Zeitpunkt erfolgen, an dem das eine
Nibble eines Befehls schon zum LCD übertragen wurde und das andere noch
nicht. Und wenn man das für alle Kommandos analysiert, dann kommt man
drauf, dass der schlimmste Fall dann eingetreten ist, wenn das LCD noch
auf 1 Nibble wartet. D.h. der ersten der 3 0x30 ist dann dann dafür da,
dass das LCD eine erst mal begonnene Aktion auch noch abschliesst und
erst die nächsten beden Nibbles mit jeweils 0x30 schalten das LCD dann
erst mal zurück auf 8 Bit Interface, von wo aus dann der erste gezielte
0x20 wieder in den 4 Bit Modus zurückführt.
> Soll ich die init-Funktion trotzdem so umschreiben, wie du beschrieben> hast?
Ich würds so probieren. Mehr als nicht funktionieren kann es nicht.
Ok, dann werde ich es so probieren und melde mich dann wieder hier.
Merkwürdig ist aber, dass es ja funktioniert, jedoch nur nach einem oder
mehreren (immer unterschiedlich) resets.
Felix H. schrieb:> Ok, dann werde ich es so probieren und melde ich dann wieder hier.>> Merkwürdig ist aber, dass es ja funktioniert, jedoch nur nach einem oder> mehreren (immer unterschiedlich) resets.
Reset oder Ein/AUsschalten?
Das ist nicht dasselbe! Denn nach dem Ein/AUsschalten ist das LCD
gesichert in einem ganz bestimmten Modus.
Wenn du aber nur den Prozessor resettest, dann ist nicht sicher
gestellt, wie die interne Logik des LCD zu diesem Zeitpunkt gerade
steht, wenn der Mega erneut mit der Intialisierungssequenz beginnt.
Karl Heinz schrieb:> Du hast recht, die ist tatsächlich dort so angegeben.> Funktional sollte es eigentlich aufs gleiche rauslaufen. Da hab ich mich> wohl davon leiten lassen, dass der Anfang der Initialisierung nicht so> aussieht, wie er normalerweise aussieht.
Wenn ich mir das nochmal durch den Kopf gehen lasse und das in den
Zusammenhang damit bringe, warum man am Anfang üblicherweise 3-mal 0x30
ausgibt, dann komme ich zum Schluss, dass die dort angegebene Sequenz
falsch ist und nicht immer funktioniert.
Karl Heinz schrieb:> Reset oder Ein/AUsschalten?
Reset.
Ich beschreibe mal was passiert:
Ich schalte die gesamte Schaltung ein -> 2 schwarze Balken auf dem LCD
-> Balken verschwinden, aber keine Zeichen erscheinen
Dann resette ich den ATmega ein paar Mal -> Balken auf LCD verschwinden,
Zeichen erscheinen auf dem Display
Direkt nach dem Einschalten funktioniert es eigentlich nie.
Karl Heinz schrieb:> Karl Heinz schrieb:>>> Du hast recht, die ist tatsächlich dort so angegeben.>> Funktional sollte es eigentlich aufs gleiche rauslaufen. Da hab ich mich>> wohl davon leiten lassen, dass der Anfang der Initialisierung nicht so>> aussieht, wie er normalerweise aussieht.>> Wenn ich mir das nochmal durch den Kopf gehen lasse und das in den> Zusammenhang damit bringe, warum man am Anfang üblicherweise 3-mal 0x30> ausgibt, dann komme ich zum Schluss, dass die dort angegebene Sequenz> falsch ist und nicht immer funktioniert.
Ok, ich probiere deine beschriebenen Vorgehensweise und melde mich dann
wieder.
Vielen Dank.
Felix H. schrieb:> Mit dieser Initialisierung> funktioniert es endlich.
Die ist auch logisch.
Die im Datenblatt angegeben ist es nicht.
1
erste Ausgabe 0x30 das LCD ist nach dem Power Up im 8 Bit Modus
2
3
nächste Ausgabe 0x20 da das LCD im 8 Bit Modus ist, wird das als kompletter
4
Befehl angesehen. Das LCD schaltet auf 4 Bit
5
6
nächste Ausgabe 0x80 Die 0x80 sind eigentlich die 2.te Hälfte des voorhergehenden
7
Befehls (0x20). Da das LCD zu diesem Zeitpunkt aber noch
8
im 8 Bit Modus war, sind die 0x20 schon als Befehl angesehen
9
worden und jetzt beginnt der nächste.
10
Müsste man jetzt ergründen, was das LCD mit 0x80 macht.
11
Auf jeden Fall nicht das, was beabsichtigt wurde
12
13
nächste AUsgabe 0x20 diese 0x20 werden zu den 0x80 von vorher dazugestoppelt,
14
da ja das LCD nach der ersten 0x20 bereits in den 4 Bit
15
Modus geschaltet hat und mit der vorhergehenden 0x80
16
ein Nibble des vermeintlich nächsten Befehls,
17
zumindest aus Sicht des LCD, übertragen wurde
und so gehts dann immer weiter: High-Nibble und Low-Nibble sind komplett
vertauscht.
Nach ein paar Resets erwischt du dann zufällig mit dem Reset mal das
Prgogramm in der Situation, dass es das High-Nibble schon ausgegeben hat
und das LCD noch auf das Low-Nibble noch wartet. Der Prozessorreset
führt dann dazu, dass erst mal wieder die 0x30 ausgegeben werden, welche
das LCD als das Low-Nibble des noch ausstehenden Daten/Kommando Bytes
auffasst. Wenn dann der Prozessor mit der 0x20, 0x80 Sequenz loslegt,
dann ist er tatsächlich mit dem LCD synchron, welches Nibble gerade
übertragen wird. Und erst dann funktioniert alles so wie es soll.
Die ganze Sequenz aus dem Datenblatt macht wenig Sinn. Der Fehler ist,
dass die erste Umschaltung in den 4 Bit Modus noch als ein 8 Bit Befehl
angesehen werden muss, der in einem Rutsch (also nicht auf 2 mal)
übertragen wird. Und erst dann kann der Eiertanz mit jeweils 2
Übertragungen für 1 Byte losgehen.
Felix H. schrieb:> Ganz großes Dankeschön Karl Heinz! Mit dieser Initialisierung> funktioniert es endlich.>> Super! Ich freue mich.
Die Delays kannst du jetzt sukzessive verkürzen, wenn du willst.
Ist zwar sicher kein Beinbruch, wenn sie so lange bleiben, aber muss ja
nicht sein.
Ja, das werde ich alles nach und nach noch anpassen.
Danke für die Tipps und auch für die ausführliche Erklärung der
Initialisierung!
Viele Grüße
Felix