www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Probleme mit GLCD


Autor: Cri (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Cri (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
und die Header- Datei

mfg Cri

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat keiner ne Idee?

Autor: Joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 
:-|

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
:) Hi Joe

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

Autor: Hauke Radtki (lafkaschar) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für das Angebot aber in Assembler schnall ichs noch weniger :)

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);
}

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Cri (Gast)
Datum:

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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
'a' hat 0x61.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);
}

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 !

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Cri (Gast)
Datum:

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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Autor: holger (Gast)
Datum:

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

Autor: Cri (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
nee...den address pointer hab ich gesetzt. ich post mal den mainpart

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 !

Autor: Cri (Gast)
Datum:

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

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Gast

>aber Pause machen ist sicher hilfreich

Genau. Ich leg mich jetzt mal hin.

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
guts nächtle :)

Autor: Günter R. (galileo14)
Datum:

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

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
volatile? Wieos?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin, moin

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

Autor: Cri (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist mit dem Reset vom LCD. Liegt der auf high ?

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :/

Autor: Cri (Gast)
Datum:

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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Reset wars net

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Cursor positionieren funzt :)

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

Autor: Cri (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);
}

Autor: Günter R. (galileo14)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.