Forum: Mikrocontroller und Digitale Elektronik Kleines Problem beim T6963C (Grafik Modus)


von Jemand (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe ein Problem mit der Ansteuerung meines Grafik Displays. Ich 
habe mir ein Display mit 240*128 Pixeln und dem T6963C Controller drauf 
gekauft. Den Textmodus habe ich bereits im Griff und nun wollte ich mich 
am Grafikmodus versuchen allerdings scheint es nicht ganz zu klappen.

Wie gesagt der Textmodus läuft ohne Probleme. Und mein Problem beim 
Grafikmodus ist folgendes: Ich möchte lediglich zum Verständnis des 
Controllers ein einziges Bit/Pixel auf dem Display an einer gewählten 
Stelle setzten. Aus dem Datenblatt habe ich erlesen, dass man wie folgt 
vorgehen soll:

*1. Die Adresse setzten*
(Das mache ich mit der selben Funktion mit der ich auch im Textmodus die 
Zeilen und Spalten angesteuert habe)

*2. Die Statusbits überprüfen*

*3. Den Befehl für Bit Set senden*

Hier ist meine Initialisierung mit den entsprechenden Speicherbereichen 
für die beiden Modi (hoffentlich richtig berechnet --> Text braucht min. 
480 Bytes und Grafik braucht min. 3840 Bytes):
1
void GLCD_Initialisierung(void)
2
{
3
  LCD_RST = 0;
4
  Delay10TCYx(10);
5
  LCD_RST = 1;
6
7
  LCD_CE = 1;  
8
9
// Grafikbereich im Speicher 768 - 8192
10
  GLCD_Daten  (0x00);    // Grapic home address (low)
11
  GLCD_Daten  (0x03);    // ...(high)
12
  GLCD_Befehl (0x42);    // ...
13
14
  GLCD_Daten  (0x00);    // Graphic area set (low)
15
  GLCD_Daten  (0x12);    // ...(high)
16
  GLCD_Befehl (0x43);    // ...
17
18
// Text Bereich im Speicher 0-512
19
  GLCD_Daten  (0x00);    // Text home adress (low)
20
  GLCD_Daten  (0x00);    // ...(high)
21
  GLCD_Befehl (0x40);    // ...
22
23
  GLCD_Daten  (0x00);    // Text area set (low)
24
  GLCD_Daten  (0x02);    // ...(high)
25
  GLCD_Befehl (0x41);    // ...
26
27
// Weiteres
28
  GLCD_Befehl (0x80);    // Mode set (OR)
29
  GLCD_Befehl (0x9C);    // Display mode (Grafik und Text)
30
31
  Display_Loeschen();

Die Routine Display_Löschen ist ebenfalls die selbe wie vom Textmodus:
1
void Display_Loeschen(void)
2
{
3
  unsigned char i;
4
5
  GLCD_Position(1,1);
6
7
  for(i=0; i<(GLCD_Cols * GLCD_Height/64); i++)
8
  {
9
       GLCD_Schreiben(' '); GLCD_Schreiben(' ');
10
       GLCD_Schreiben(' '); GLCD_Schreiben(' ');
11
       GLCD_Schreiben(' '); GLCD_Schreiben(' ');
12
       GLCD_Schreiben(' '); GLCD_Schreiben(' ');
13
    } 
14
  GLCD_Position(1,1);
15
}

Die Routine zum Bit Set habe ich in den Anhang geladen, da sonst wegen 
der Kommentare hier in der Browseransicht alles verschoben wäre.

Ich freue mich auf Rückmeldungen =)
Gruß Hans

von Jemand (Gast)


Lesenswert?

Das wichtigste habe ich vergessen: Das Display möchte ich halt in beiden 
Modi gleichzeitig betreiben. Ich habe ganz oben in der ersten Zeile 
(1,1)  einen Text ausgegeben. Und in der Zeile 5 Spalte 5 möchte ich das 
Bit 5 setzten:
1
  GLCD_Zeichenkette("Multimedia Modul");
2
  Pixel_setzten(5,5,5);

Und das Display sieht folgendermaßen aus: Es ziehen sich von oben nach 
unten Streifen übers ganze Display. Und man kann den Text erahnen, 
welcher ebenfalls wie die Striche nach unten wiederholt wirkt.

von Jemand (Gast)


Angehängte Dateien:

Lesenswert?

Hier ein Foto

von Jemand (Gast)


Lesenswert?

Wenn ich mal gar nichts schreibe dann bleiben diese Streifen da. Also 
lösche ich das Display möglicherweise nicht richtig?

von spess53 (Gast)


Lesenswert?

Hi

Was mir erstmal auffällt sind deine Werte für Text- und Grafikarea. Bei 
einem 240 Pixel breiten Display und einem 8x8 Font sollten beide Werte 
$1E (30) sein. Das sind die dargestellten Byte in einer Zeile.

MfG Spess

von Jemand (Gast)


Lesenswert?

Achso. Ich dachte das wäre quasi ein Bereich indem Platz wäre um das 
Display einmal zu füllen.. Aber wie wählt man dann die Home Adressen 
aus? Einfach nur, dass sie sich nicht überlagern?

(Jetzt bekomme ich einfach nur wilde Punkte überall.)

Also sehe es so aus:
1
// Grafikbereich im Speicher 768 - 8192
2
  GLCD_Daten  (0x00);    // Grapic home address (low)
3
  GLCD_Daten  (0x03);    // ...(high)
4
  GLCD_Befehl (0x42);    // ...
5
6
  GLCD_Daten  (0x1E);    // Graphic area set (low)
7
  GLCD_Daten  (0x00);    // ...(high)
8
  GLCD_Befehl (0x43);    // ...
9
10
// Text Bereich im Speicher 0-512
11
  GLCD_Daten  (0x00);    // Text home adress (low)
12
  GLCD_Daten  (0x00);    // ...(high)
13
  GLCD_Befehl (0x40);    // ...
14
15
  GLCD_Daten  (0x1E);    // Text area set (low)
16
  GLCD_Daten  (0x00);    // ...(high)
17
  GLCD_Befehl (0x41);    // ...

von Jemand (Gast)


Lesenswert?

Okay ich habe gerade gesehen, dass ich wohl nochmal gezielt den 
Grafikspeicher löschen muss. Ich melde mich wieder =)

von spess53 (Gast)


Lesenswert?

Hi

Mit folgenden Werten funktioniert es bei mir:

    .equ grahome   = $0000                ;Gafic Home Adress
    .equ txthome   = $1700                ;Text Home Adress(4kByte)

    .equ graarea   = $1e                  ;Grafic Area
    .equ txtarea   = $1e                  ;Text Area

MfG Spess

von Jemand (Gast)


Angehängte Dateien:

Lesenswert?

Aber es ist doch egal ob ich den Textspeicher vor oder hinter dem 
Grafikspeicher habe oder etwa nicht?

Danke für deine Hilfe btw. =)

Also ich habe jetzt folgende Werte (Wenn ich deine Werte übernehme 
funktioniert meine Textausgabe nicht mehr):
1
GLCD_Daten  (0x00);    // Grapic home address (low)
2
GLCD_Daten  (0x03);    // ...(high)
3
..
4
5
GLCD_Daten  (0x1E);    // Graphic area set (low)
6
GLCD_Daten  (0x00);    // ...(high)
7
..
8
9
GLCD_Daten  (0x00);    // Text home adress (low)
10
GLCD_Daten  (0x00);    // ...(high)
11
..
12
13
GLCD_Daten  (0x1E);    // Text area set (low)
14
GLCD_Daten  (0x00);    // ...(high)
15
..

Und ich habe jetzt mal wie folgt versucht das Display zu löschen indem 
ich den ganzen Speicher mit 0en fülle:
1
void Speicher_Loeschen(void)
2
{
3
  unsigned int i;
4
5
  Speicher_Adresse(0x0000);
6
7
  for(i=0; i<(0xFFFF); i++)
8
  {
9
       GLCD_Daten(0);
10
    } 
11
  GLCD_Position(1,1);
12
}
13
14
void Speicher_Adresse (unsigned int Adresse)
15
{
16
  GLCD_Daten(Adresse%256);
17
  GLCD_Daten(Adresse>>8);
18
  GLCD_Befehl(0x24);
19
}

Wenn ich jetzt schreibe scheint es fast zu klappen bis auf eine 
Kleinigkeit. Anstatt dass nur 1 Pixel gesetzt wird erscheint ein Zeichen 
könnte ein @ sein (siehe Anhang).

von spess53 (Gast)


Lesenswert?

Hi

>Wenn ich jetzt schreibe scheint es fast zu klappen bis auf eine
>Kleinigkeit. Anstatt dass nur 1 Pixel gesetzt wird erscheint ein Zeichen
>könnte ein @ sein (siehe Anhang).

Dann schreibst du in den Textspeicher.

>  GLCD_Daten(Adresse%256);
>  GLCD_Daten(Adresse>>8);
>  GLCD_Befehl(0x24);

Hast du den Anfang des Grafikspeichers berücksichtigt. Das Byte links 
oben ist Grafik Home.

MfG Spess

von Jemand (Gast)


Lesenswert?

Ich orientiere mich i.M. an dem hier:
http://www.mikrocontroller.net/attachment/highlight/16188

Und stecke grad in der Funktion "glcd_setpixel" fest in folgender Zeile:
1
addr =  glcd_G_BASE + (row*glcd_BYTES_PER_ROW)  + (column/8);

Hier wird doch nun die Adresse zusammen geschustert an der im RAM dann 
das Pixel gesetzt werden soll, richtig? Warum addiert er hinten 
(colums/8)? Wird somit nicht bei einem 16 Zeilen (128 Pixel) Display 
nicht immer das 2 Pixel gesetzt also Bit 1? Oder verstehe ich das gerade 
falsch..

Ich bin mal zum Zahnarzt hehe bis später und nochmal Danke ;-)

von Ralf (Gast)


Lesenswert?

> Warum addiert er hinten (colums/8)?
Weil man sonst immer nur auf dem ersten Byte der entsprechenden Zeile 
landet.

Ralf

von chris (Gast)


Lesenswert?


von Jemand (Gast)


Lesenswert?

Ich bin ehrlich gesagt gerade ein bisschen am Verzweifeln. Ich habe 
meine Routinen jetzt folgendermaßen:

Ich habe jetzt die Werte von Spess übernommen für die Homeadressen.
1
// 0x0000 = 0
2
  GLCD_Daten  (0x00);    // Grapic home address (low)
3
  GLCD_Daten  (0x00);    // ...(high)
4
  GLCD_Befehl (0x42);    // ...
5
6
  GLCD_Daten  (0x1E);    // Graphic area set (low)
7
  GLCD_Daten  (0x00);    // ...(high)
8
  GLCD_Befehl (0x43);    // ...
9
10
// 0x1700 = 5888
11
  GLCD_Daten  (0x00);    // Text home adress (low)
12
  GLCD_Daten  (0x17);    // ...(high)
13
  GLCD_Befehl (0x40);    // ...
14
15
  GLCD_Daten  (0x1E);    // Text area set (low)
16
  GLCD_Daten  (0x00);    // ...(high)
17
  GLCD_Befehl (0x41);    // ...
18
19
// Weiteres
20
  GLCD_Befehl (0x80);    // Mode set (OR)
21
  GLCD_Befehl (0x9C);    // Display mode (Grafik und Text)
22
23
24
  Speicher_Loeschen();  // Den gesamten Speicher löschen

Speicher löschen ruft nacheinander diese beiden Funktionen auf, welche 
den gesamten Inhalt des RAMs löschen sollen indem sie 0en hinein 
schreiben:
1
void Grafik_Speicher_Loeschen(void)
2
{
3
  unsigned int i;
4
5
  Speicher_Adresse(0x0000);
6
7
  for(i=0; i<(0x16FF); i++)
8
  {
9
       GLCD_Daten(0);
10
    } 
11
  GLCD_Position(1,1);
12
}
1
void Text_Speicher_Loeschen(void)
2
{
3
  unsigned int i;
4
5
  Speicher_Adresse(0x1700);
6
7
  for(i=0x1700; i<(0xFFFF); i++)
8
  {
9
       GLCD_Daten(0);
10
    } 
11
  GLCD_Position(1,1);
12
}

Eigentlich habe ich mir vorgestellt, dass nun das Display leer ist. Aber 
Pustekuchen =( es ist voller Müll.

So sieht meine Routine aus um zu einer bestimmten Speicheradresse zu 
springen. Im Prinzip ist es die selbe wie hier:
http://www.mikrocontroller.net/attachment/highlight/16188

Nur leicht geändert, da meine Ausgabe-Funktionen mit 8 Bit arbeiten. 
Also habe ich die 16 Bit Adresse in zwei 8 Bit Variablen gewandelt und 
übertrage diese einzeln. Erst Low, dann High.
1
void Speicher_Adresse (unsigned int Adresse)
2
{
3
  unsigned char Low;
4
  unsigned char High;
5
6
  Low = Adresse&255;
7
  Adresse=Adresse>>8;
8
  High = Adresse&255;
9
  
10
  GLCD_Daten(Low);
11
  GLCD_Daten(High);
12
  GLCD_Befehl(0x24);
13
}

>Hast du den Anfang des Grafikspeichers berücksichtigt. Das Byte links
>oben ist Grafik Home.

Das verstehe ich nicht, was meinst du damit?

Nabend

von Jemand (Gast)


Lesenswert?


von Jemand (Gast)


Lesenswert?

Okay ein Fehler ist gefunden! Bei den Routinen:
- void Grafik_Speicher_Loeschen(void)
- void Text_Speicher_Loeschen(void)
fehlte jeweils der Befehl: GLCD_Befehl  (0xC0); in der for Schleife.

So ich versuche mich weiter... pfff

von Jemand (Gast)


Lesenswert?

Kann es sein, dass der C18 hier wieder irgendwas krankes optimiert?
1
ADR = ((X-1)*30)+((Y-1)/8);

Diese Rechnung ergibt bei X=64 und Y=120 nämlich nicht 1904.. Warum??
Wenn ich folgendes schreibe wird auch 1904 in die Variable ADR (unsigned 
int) geschrieben:
1
ADR=1904;

von gerd (Gast)


Lesenswert?

Jemand schrieb:
> Wenn ich folgendes schreibe wird auch 1904 in die Variable ADR (unsigned
> int) geschrieben:
> ADR=1904;

Sicher?
unsigned int ist doch 8bit also mit einem Wertevorrat bis max. 255 ?!

- gerd

von Jemand (Gast)


Lesenswert?

Ne, char ist 8 Bit. Int(eger) ist 16 Bit.

von gerd (Gast)


Lesenswert?

Welcher Compiler?

- gerd

von Jemand (Gast)


Lesenswert?

Fakt ist, ich möchte die Rechnung durchführen aber es funktioniert 
komischerweise nicht.

Also das hier funktioniert nicht:
1
Pixel_setzten(64,120);
2
3
void Pixel_setzten(unsigned char X, unsigned char Y)
4
{
5
unsigned int ADR;    // Zur Berechnung der RAM Adresse
6
ADR = 0;      // Die Grafik Home Adresse
7
8
if ( (X>128) | (Y>240) )   // Wenn der adressierte Bereich
9
{        // außerhalb des Displays liegt,
10
  return;      // dann springe sofort zurück!
11
}  
12
13
ADR = ((X-1)*30)+((Y-1)/8);  
14
ADR = 1904;
15
16
Speicher_Adresse(ADR);
17
Busy_Abfrage();      // Nachfragen ob das Display fertig ist
18
19
GLCD_Befehl (0xF8+1);            
20
}

Das dann schon:
1
Pixel_setzten(64,120);
2
3
void Pixel_setzten(unsigned char X, unsigned char Y)
4
{
5
unsigned int ADR;    // Zur Berechnung der RAM Adresse
6
ADR = 0;      // Die Grafik Home Adresse
7
8
if ( (X>128) | (Y>240) )   // Wenn der adressierte Bereich
9
{        // außerhalb des Displays liegt,
10
  return;      // dann springe sofort zurück!
11
}  
12
13
ADR = ((X-1)*30)+((Y-1)/8);  
14
ADR = 1904;  <--------------------------------------
15
16
Speicher_Adresse(ADR);
17
Busy_Abfrage();      // Nachfragen ob das Display fertig ist
18
19
GLCD_Befehl (0xF8+1);            
20
}

Aber warum denn?

von Jemand (Gast)


Lesenswert?

Sorry wegen Doppelpost!

Compiler C18 (Microchip)

von Jemand (Gast)


Lesenswert?

Hab den Fehler gefunden!

Im Programkopf muss unsigned int X und Y stehen. Ich verstehe allerdings 
nicht ganz wieso. Kann mir das jemand erklären?

Also ist es so, dass zunächst (bei der Rechnung) X-1 und dann *30 UND 
DAS wird dann erst in X geschrieben bevor es in ADR kommt?

von gerd (Gast)


Lesenswert?

Jemand schrieb:
> Compiler C18 (Microchip)

Ah, ok. Da kann ich nicht mitreden. Wenn du aber dennoch diesen Fehler 
zumindest ausschliessen willst, dann mach doch einfach mal ein sizeof - 
esseidenn du bist dir sicher.. ;)

- gerd

von gerd (Gast)


Lesenswert?

Jemand schrieb:
> Also ist es so, dass zunächst (bei der Rechnung) X-1 und dann *30 UND
> DAS wird dann erst in X geschrieben bevor es in ADR kommt?

Korrekt - wie sollte es denn sonst laufen. Wenn du es die als Listing 
anzeigen lässt, sollte auch klar werden warum. Das Ganze läuft ja 
sequentiell ab. Das es hier in C so schön in eine Zeile passt heisst ja 
nicht, dass es so durch Comiler auch in einem Befehl bearbeitet werden 
kann (wie auch - sind ja schon alleine vier Rechenbefehle).

- gerd

von Jemand (Gast)


Lesenswert?

Das macht Sinn. Dankeschön gerd!

von Jemand (Gast)


Angehängte Dateien:

Lesenswert?

So nun habe ich das Display im Griff.

von Spess53 (Gast)


Lesenswert?

Hi

>So nun habe ich das Display im Griff.

Na, geht doch. Aber eine Frage: Warum fängst du mit der Spalten- und 
Zeilenzählung nicht bei 0 an? Deine Berechnungen vereinfachen sich und 
werden dadurch auch schneller.

MfG Spess

von Jemand (Gast)


Lesenswert?

Hab ich mir ehrlich gesagt gar keine Gedanken drum gemacht. Macht es 
denn so einen großen unterschied? Ich meine ist nur hier und da eine 
Subtraktion um 1.

von Spess53 (Gast)


Lesenswert?

Hi

>Ich meine ist nur hier und da eine Subtraktion um 1.

Kommt darauf an, was dein Compiler daraus macht. Und es ist nicht nur 
die -1

Was passiert hier:

>if ( (X>128) | (Y>240) )  ....

 bei X oder Y =0?

MfG Spess

von Jemand (Gast)


Lesenswert?

Ja das war da noch nicht vollständig, schaut jetzt so aus:
1
if ( (X>240) | (Y>128) | (X==0) | (Y==0) )

von Spess53 (Gast)


Lesenswert?

Hi

Persönlich vermeide ich jeden unnötigen Code.

Abgesehen davon verstehe ich nicht so richtig weshalb so oft 
Pixelsetzen/löschen benutzt wird. Ich habe das in 12 Jahren mit 
T6962-Displays erst einmal benutzt. Selbst in dem Projekt

Beitrag "Re: Zeigt her Eure Kunstwerke !"

wird kein einziges einzelnes Pixel gesetzt oder gelöscht.

MfG Spess

von Jemand (Gast)


Lesenswert?

Ja gut. Ich fange gerade erstmal an das Teil ein wenig zu verstehen ^^

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.