Hi Leute. Habe mich nun an ein Grafik LCD rangemacht (Controller T6963). Ich bekomm aber leider nix auf das GLCD. Komm net drauf was es ist. Wäre sehr froh wenn ihr mir weiter helfen könntet.
Christian, nen bischen ungeduldig heute ;-)) http://www.8052.com/codelib.phtml hier findest du fertigen code den du sicherlich anpassen kannst, nen bischen nach unten scrollen, GLCD ist dabei. Habe gerade für den KS108 nen Treiber in Arbeit aber das hilft dir nicht :-|
:) Hi Joe ungeduldig bin ich schon gewesen...muss ich zugeben :) aber auch nur deswegen weil ich schon seit 2h den Fehler suche :)
>weil ich schon seit 2h den Fehler suche :) Ist doch garnix ;) Ich könnte dir Assembler Code anbieten ... ist aber in keinster Weise optimiert ;) Edit: oh ich seh gerade du benutzt nen AT89C2051 mein code wäre fürn AVR gewesen ... hilft dir also wohl nicht.
Sieht doch ganz gut aus. Init ist ok. Deine Werte für Text/Grapharea habe ich auch schon benutzt. Das könnte man mal probieren: _Set(RD); in Checkbusy() vieleicht doch in die while loop mit rein. void WR_Cmd(u_char cmd, u_char state){ Check_Status(state); _Data_Port = cmd; _Set(CD); _Set(RD); _Clear(WR); _Clear(CE); wait(1); _Set(CE); _Set(WR); }
Ganz vergessen: void wr_a(void){ WR_Data((0x21-0x20), _STA_01); WR_Cmd(_WR_Incr, _STA_01); } Ein 'A' hat Hexcode 0x41 ;) Schreib doch einfach 'A'-0x20.
Hi Holger 0x21 ist das kleine a wenn ich mich net täusche. Das mit dem wait hab ich schon mal probiert aber ohne Erfolg :/ Noch ne andere Idee?
ne, is doch ein Rufzeichen :) Aber das is ja net weiter schlimm...wichtig wärs das ich es aufs display bekomme
Dein Busy Check gefällt mir nicht. Die Abfrage mit dem ? versteh ich nicht :( Schande über mich. Nie selber benutzt. So ungefähr sieht ein Busy-Check bei mir auf nem Atmega aus: void Check_Status(u_char state){ // Manual mode check u_char busy; _Set(CD); //einmal reicht _Set(WR); //einmal reicht do{ _Clear(CE); _Clear(RD); wait(1); busy = _Data_Port; _Set(RD); _Set(CE); }while((busy & state) == state); }
Also bei deinem Vorschlag fällt mein buys-flag weg. Da müsstest du in der letzten Zeile aber while((_Data_Port & state) == state); stehen haben. void Check_Status(u_char state){ // Manual mode check bit busy = 1; while(busy){ _Set(CD); _Set(WR); _Clear(RD); _Clear(CE); wait(1); busy = ((_Data_Port & state) == state)? 0:1; _Set(CE); } _Set(RD); Mein Busy-Check is eigentlich das selbe. Ich frage halt das Port ab und vergleiche es mit 0x03(STA0 & 1). Wenn Das Ergebnis( mittels dem ?)wahr ist bekomm ich ne 0 zurück und die while - Schleife wird beendet. Ansonsten wird ne 1 ins busy geschrieben und die while-Schleife läuft so lange bis da ne 0 daher kommt. müsste doch funzn oder peil ichs grad net?
>while((_Data_Port & state) == state); stehen haben.
Nein. Siehe busy = _Data_Port;
_Data_Port wäre bei meiner Schleife an der
Stelle tödlich !
>Das Ergebnis( mittels dem ?)wahr ist bekomm ich ne 0 zurück und die >while - Schleife wird beendet. Ne, deine Schleife ist schon korrekt, meine ist falsch. Hab das mit dem ? grad mal nachgelesen. }while((busy & state) == state); muss }while((busy & state) != state); lauten. So stehts auch in meinem Quellcode.
Also am Status Check liegt es aller Wahrscheinlichkeit nicht. Gut zu wissen aber :) Nu muss ich mich weiter mühen um den blöden Fehler zu finden. Keine Ahnung was da net passt. Muss ich eigentlich noch was anderes berücksichtigen (außer set_address) wenn ich irgendeinen Buchstaben ausgeben will? Was ich noch net ganz verstanden habe ist das mit der Text home address und der Graph home address (CGRAM & CGROM hab i a net verstanden). Was ist eigentlich damit gemeint? Wird in diesem Bereich der grad ausgegebene Text(Grafik) zwischengespeichert oder was geschieht hierbei?
>Was ich noch net ganz verstanden habe ist das mit der Text home address >und der Graph home address (CGRAM & CGROM hab i a net verstanden). Was >ist eigentlich damit gemeint? Wird in diesem Bereich der grad >ausgegebene Text(Grafik) zwischengespeichert oder was geschieht hierbei? Ja, so ist es. Dein Display hat ein SRAM hinten drauf ! Die Texthomeadress gibt an wo dein Textbereich startet. Die Graphhomeadress gibt an wo dein Grafikbereich startet. Normalerweise lege ich den Textbereich vor den Grafikbereich. Da muss man aber je nach Einstellung etwas aufpassen, denn beide dürfen sich nicht überschneiden. Die Länge des Textbereiches ist abhängig davon ob du im 6 Bit oder 8 Bit Textmodus arbeitest. Die Höhe eines Zeichens ist 8 Pixel. Habe gerade gesehen das du ein 240x128 Display in der Headerdatei hast. Stell die Graphhomeadress besser mal auf 0x300. Wirst gleich sehen warum. Nehmen wir mal dein Display mit 240x128. Jedes Zeichen ist 8 Pixel hoch. Also 16 Textzeilen für dein Display. Im 8 Bit Modus hast du 30 Zeichen pro Zeile, im 6 Bit Modus 40 Zeichen pro Zeile. Im 8 Bit Modus brauchst du für 16 x 30 Zeichen Speicher. Das sind 480 Bytes. 0x200 als Graph home adress ist also ok. Im 6 Bit Modus brauchst du für 16 x 40 Zeichen Speicher. Das sind 640 Bytes. 0x200 als Graph home adress ist nicht mehr ok. Das blöde an der Geschichte: Der 6 Bit Modus ist für Textdarstellung optimal. Sieht einfach besser aus und mehr Zeichen pro Zeile darstellbar. Dann läuft aber auch die Grafik nur mit 6 Bit ! Bei 8 Bit sieht der Text sch..lecht aus aber mit Grafik ist das arbeiten einfach schneller. Wenn dein SRAM auf dem Display groß genug ist bekommst du möglicherweise sogar mehrere Bildschirme in den Speicher ! Aber das ist ne andere Geschichte. Holger
tolle Erklärung! Danke. Wie ist das eigentlich gemeint mit den Bildschirmen? Denk mal so: Hab da z.B. einen "Willkommens Bildschirm",einen "Menu Bildsch." usw. Ist das so richtig oder nicht? Wenn ja...wohin speichere ich diese? In den Grafikbereich? Im Textbereich wäre ja net Platz für den Code eines ganzen Bildschirmes. Oder sollte man da besser auf einen externen Speicher zurück greifen?
Ich glaub das wird ne längere Aktion ;) Und dein Display läuft noch nicht mal. Na gut ich versuchs mal: Beim T6963 gibt es erstmal zwei Sorten Bildschirme. Den Textbildschirm und den Grafikbildschirm. Beide werden einfach übereinandergelegt (ODER Verknüpfung). Könnte sein das das ODER auch per Parameter auf EXOR geändert werden kann, aber das habe ich noch nicht probiert. Textbildschirm und Grafikbildschirm sind unabhängig voneinander. D.h. du kannst den Textbildschirm löschen ohne den Grafikbildschirm zu löschen. Der bleibt dann einfach stehen. Umgekehrt gehts genauso. Es sind ja zwei verschiedene Speicherbereiche. Du kannst bei genügend Speicher (SRAM auf dem Display !) mehrere Textbildschirme und Grafikbildschirme benutzen. Das musst du dem T6963 aber auch mitteilen. Wenn du z.B. zwei Textbildschirme nutzen möchtest, verschiebst du einfach die Graph home adress weiter nach oben (z.B. 0x600) um Platz für zwei Textbildschirme zu machen. Dann hast du einen sichtbaren Teil des Textbildschirmes und einen unsichtbaren Teil. Es können ja nur 16 Textzeilen angezeigt werden. Um in den unsichtbaren Teil des Textbildschirmes zu kommen programmierst du die Text home adress einfach neu. Das geht auch Zeile für Zeile (Scrolling). Beim Grafikschirm kannst du das genauso machen. Mein Display hat genug Speicher für zwei Grafikschirme. Die kann ich durch umprogrammieren der Graph home adress pixelweise rauf und runterscrollen. War das verständlich ? holger
jap war es :) Vielen Dank! Nu hab ich ja einiges übers glcd gelernt. Jetzt sollte es nur noch laufen damit ich auch ausprobieren kann was das GLCD alles hergibt :)
Dein Code sieht gut aus. Wahrscheinlich hast du in deinem Testprogramm einfach irgendwo nur Set adress pointer vergessen.
Denk das ne weitere Fehlerquelle vielleicht ne zu lange Datenleitung ist. War beim meinem LCD auch mal der Fall. Die Datenleitung war an die 20cm. Aber trotzdem hab ich am LCD was gesehen nur das anstatt Elektronik z.B. Ektink gestanden ist. hmm...kannst da mal mein main anschauen? vielleicht liegts eher in der Software
In deiner main steht das du 12 Millionen mal pro Sekunde das Zeichen 'a' an Position 0x20 schreibst. Mach doch mal ne Pause zwischendurch !
jap...dies dürft jedoch net den Unterschied machen oder ? Die Pause werd ich trotzdem einbauen :)
>In deiner main steht das du 12 Millionen mal pro Sekunde
naja nicht ganz 12 Millionen mal ... aber Pause machen ist sicher
hilfreich ... und das nicht nur beim display. Hab mal acht Stunden nach
einem Fehler gesucht und am nächsten Tag fiel mir der Fehler auf Anhieb
auf.
@ Gast
>aber Pause machen ist sicher hilfreich
Genau. Ich leg mich jetzt mal hin.
Moin, moin Wo schaltest du beim BusyCheck P1 auf Eingang ? Du willst ja schliesslich was vom Display lesen.
Guten Morgen. Hab mich so gefreut als ich das gelesen habe (mit P1). Is ja logo...Voller Freude geändert und ... NIX . Ich packs nich...keine Ahnung was ich noch alles probieren soll Hier is mal mein aktuelles C-File(net all zu viel geändert) lg Cri
jap,tut er. Hab ich in ner FUnktion (Reset() ) geschrieben. Dachte zuerst auch das es das sein kann also hab ich dann die Fkt. geschrieben . Setze vor der Init einmal Reset...aber was anderes als NIX kommt da net :/
Muss dir mal ein riesen DANKE aussprechen Holger. Deine Bereitschaft mir zu helfen ist lobenswert!!!!
Bitte ! Wartest du nach Reset high noch ein wenig ? Ansonsten würde ich mal am Kontrast rumdrehen. Mehr fällt mir jetzt auch nicht mehr ein.
Also ich bin einer der dümmsten die ich kenne. Habe die Anschlüsse am GLCD genau verkehrt gehabt. Dort wo P1^0 sein sollte war P1^7 usw. ! Jetzt seh ich am LCD wenigstens mal einen Haufen Müll! Aber das ist ja schon mal was. Ist das normal das man nach der Init einen eher undefinierten Screen hat? das mit dem Warten nach dem Reset werd ich auch gleich ausprobieren.
Ja, der "Müll" ist normal, weil nach dem Einschalten das SRAM auf dem Display einen undefinierten Zustand hat, alle Bytes sind mit zufälligen Werten gefüllt. Wenn du das Display-ON-Kommando sendest, bevor du das RAM löschst, siehst du die zufälligen Werte direkt aufm Display. Der Display-On Befehl sollte daher einer der letzten Befehle der GLCD-Initialisierung sein. Das RAM-Löschen gehört eben zur Initialisierung. Ralf
Hab das RAM nun gelöscht und ich erhalte einen wunderschönen weißen Screen :) Nur das beschreiben will net ganz. Reicht doch wenn ich set_addr(0x30) // z.B und wr_a(); sende oder?
Cursor positionieren funzt :) Ich freu mich jetzt schon über jeden kleinen Schritt :)
Hi Holger. Ich kann nicht einen beliebigen Buchstaben am LCD setzen. Schreib ich z.B. set_addr(0x0); und wr_c(); dann fängt er beim 4ten Pixel(in der Reihe) mit C an und füllt es mir bis nach unten auf (nur diese eine Spalte wo eben das c steht). Aber das macht er nur an der pos 0. sonst rührt sich nichts :/ Hast du ne Ahnung was da sein kann?
>Hast du ne Ahnung was da sein kann?
Nein. Da bin ich auch etwas ratlos. set_addr() sieht richtig
aus. Dein wr_a() sieht auch ok aus. Der Opcode
für Write mit increment adress stimmt. Hat die Init nicht
geklappt ? Probier doch mal folgendes:
void init_glcd(void){
WR_Data((u_char)(_Graph_H_Addr & 0xFF), _STA_01); // Low byte
WR_Data((u_char)(_Graph_H_Addr>>8), _STA_01); // High byte
WR_Cmd(_Set_Graph_H_Addr, _STA_01);
WR_Data(_Area, _STA_01); // Low byte
WR_Cmd(_Set_Graph_Area, _STA_01);
WR_Data((u_char)(_Text_H_Addr & 0xFF), _STA_01); // Low byte
WR_Data((u_char)(_Text_H_Addr>>8), _STA_01); // High byte
WR_Cmd(_Set_Text_H_Addr, _STA_01);
WR_Data(_Area, _STA_01); // Low byte
WR_Cmd(_Set_Text_Area, _STA_01);
WR_Cmd((_Set_GLCD_Mode | _OR | _CGROM ), _STA_01);
WR_Cmd((_Set_GLCD_Attributes | _AllOn), _STA_01);
}
/* ---- Set address pointer
----------------------------------------------*/
void set_addr(unsigned int addr){
WR_Data( (u_char)(addr & 0xFF) , _STA_01); // Low byte
WR_Data( (u_char)(addr>>8) , _STA_01); // High byte
WR_Cmd( _Set_Address_pointer , _STA_01);
}
Cri wrote:
> volatile? Wieos?
Es ist die alte Sache und der klassische Fehler; in der Schleife liest
Du einen Wert ein ("busy"), der aber in der Schleife nicht weiter
verändert wird (nur halt immer neu eingelesen). Je nach Compiler und
Optimierungsstufe könnte der Compiler auf die Idee kommen, das "busy"
schon vor der Schleife einzulesen und innerhalb der Schleife nur den
eingelesenen und in einem Register gehaltenen Wert zu verwenden, was
natürlich dazu führt, daß das Busy-Flag des LCD's überhaupt nicht mehr
beachtet wird. Das kann - muß aber nicht - zu groben Fehlern führen.
Wenn man "busy" mit "volatile" definiert, wird diese Optimierung
unterlassen und das Busy-Bit wird immer korrekt verarbeitet. Man kann
aber mit guter Wahrscheinlichkeit Glück haben und der Compiler optimiert
das nicht - aber der Code ist dann nicht so portabel und im strengen
Sinne nicht korrekt.
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.