Forum: Mikrocontroller und Digitale Elektronik Probleme mit GLCD


von Cri (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Cri (Gast)


Angehängte Dateien:

Lesenswert?

und die Header- Datei

mfg Cri

von Cri (Gast)


Lesenswert?

Hat keiner ne Idee?

von Joe (Gast)


Lesenswert?

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 
:-|

von Cri (Gast)


Lesenswert?

:) Hi Joe

ungeduldig bin ich schon gewesen...muss ich zugeben :) aber auch nur 
deswegen weil ich schon seit 2h den Fehler suche :)

von Hauke R. (lafkaschar) Benutzerseite


Lesenswert?

>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.

von Cri (Gast)


Lesenswert?

Danke für das Angebot aber in Assembler schnall ichs noch weniger :)

von holger (Gast)


Lesenswert?

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);
}

von holger (Gast)


Lesenswert?

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.

von Cri (Gast)


Lesenswert?

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?

von Cri (Gast)


Lesenswert?

ne, is doch ein Rufzeichen :) Aber das is ja net weiter 
schlimm...wichtig wärs das ich es aufs display bekomme

von holger (Gast)


Lesenswert?

'a' hat 0x61.

von holger (Gast)


Lesenswert?

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);
}

von Cri (Gast)


Lesenswert?

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?

von holger (Gast)


Lesenswert?

>while((_Data_Port & state) == state); stehen haben.

Nein. Siehe     busy = _Data_Port;
_Data_Port wäre bei meiner Schleife an der
Stelle tödlich !

von holger (Gast)


Lesenswert?

>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.

von Cri (Gast)


Lesenswert?

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?

von Cri (Gast)


Lesenswert?

so...i geh nun mal laufen. Kopf frei bekommen. Mal sehen obs dann klappt 
:)

von holger (Gast)


Lesenswert?

>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

von Cri (Gast)


Lesenswert?

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?

von holger (Gast)


Lesenswert?

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

von Cri (Gast)


Lesenswert?

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 :)

von holger (Gast)


Lesenswert?

Dein Code sieht gut aus. Wahrscheinlich hast du in deinem
Testprogramm einfach irgendwo nur Set adress pointer vergessen.

von Cri (Gast)


Angehängte Dateien:

Lesenswert?

nee...den address pointer hab ich gesetzt. ich post mal den mainpart

von Cri (Gast)


Lesenswert?

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

von holger (Gast)


Lesenswert?

In deiner main steht das du 12 Millionen mal pro Sekunde
das Zeichen 'a' an Position 0x20 schreibst.

Mach doch mal ne Pause zwischendurch !

von Cri (Gast)


Lesenswert?

jap...dies dürft jedoch net den Unterschied machen oder ? Die Pause werd 
ich trotzdem einbauen :)

von gast (Gast)


Lesenswert?

>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.

von holger (Gast)


Lesenswert?

@ Gast

>aber Pause machen ist sicher hilfreich

Genau. Ich leg mich jetzt mal hin.

von Cri (Gast)


Lesenswert?

guts nächtle :)

von Günter R. (galileo14)


Lesenswert?

Vergeßt das "volatile" nicht für die Busy-Variable.

von Cri (Gast)


Lesenswert?

volatile? Wieos?

von holger (Gast)


Lesenswert?

Moin, moin

Wo schaltest du beim BusyCheck P1 auf Eingang ?
Du willst ja schliesslich was vom Display lesen.

von Cri (Gast)


Angehängte Dateien:

Lesenswert?

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

von holger (Gast)


Lesenswert?

Was ist mit dem Reset vom LCD. Liegt der auf high ?

von Cri (Gast)


Lesenswert?

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 :/

von Cri (Gast)


Lesenswert?

Muss dir mal ein riesen DANKE aussprechen Holger. Deine Bereitschaft mir 
zu helfen ist lobenswert!!!!

von holger (Gast)


Lesenswert?

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.

von Cri (Gast)


Lesenswert?

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.

von Cri (Gast)


Lesenswert?

Der Reset wars net

von Ralf (Gast)


Lesenswert?

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

von Cri (Gast)


Lesenswert?

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?

von Cri (Gast)


Lesenswert?

Cursor positionieren funzt :)

Ich freu mich jetzt schon über jeden kleinen Schritt :)

von Cri (Gast)


Lesenswert?

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?

von holger (Gast)


Lesenswert?

>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);
}

von Günter R. (galileo14)


Lesenswert?

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
Noch kein Account? Hier anmelden.