www.mikrocontroller.net

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


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

Bewertung
0 lesenswert
nicht 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):
void GLCD_Initialisierung(void)
{
  LCD_RST = 0;
  Delay10TCYx(10);
  LCD_RST = 1;

  LCD_CE = 1;  

// Grafikbereich im Speicher 768 - 8192
  GLCD_Daten  (0x00);    // Grapic home address (low)
  GLCD_Daten  (0x03);    // ...(high)
  GLCD_Befehl (0x42);    // ...

  GLCD_Daten  (0x00);    // Graphic area set (low)
  GLCD_Daten  (0x12);    // ...(high)
  GLCD_Befehl (0x43);    // ...

// Text Bereich im Speicher 0-512
  GLCD_Daten  (0x00);    // Text home adress (low)
  GLCD_Daten  (0x00);    // ...(high)
  GLCD_Befehl (0x40);    // ...

  GLCD_Daten  (0x00);    // Text area set (low)
  GLCD_Daten  (0x02);    // ...(high)
  GLCD_Befehl (0x41);    // ...

// Weiteres
  GLCD_Befehl (0x80);    // Mode set (OR)
  GLCD_Befehl (0x9C);    // Display mode (Grafik und Text)

  Display_Loeschen();

Die Routine Display_Löschen ist ebenfalls die selbe wie vom Textmodus:
void Display_Loeschen(void)
{
  unsigned char i;

  GLCD_Position(1,1);

  for(i=0; i<(GLCD_Cols * GLCD_Height/64); i++)
  {
       GLCD_Schreiben(' '); GLCD_Schreiben(' ');
       GLCD_Schreiben(' '); GLCD_Schreiben(' ');
       GLCD_Schreiben(' '); GLCD_Schreiben(' ');
       GLCD_Schreiben(' '); GLCD_Schreiben(' ');
    } 
  GLCD_Position(1,1);
}

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

Autor: Jemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
  GLCD_Zeichenkette("Multimedia Modul");
  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.

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

Bewertung
0 lesenswert
nicht lesenswert
Hier ein Foto

Autor: Jemand (Gast)
Datum:

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

Autor: spess53 (Gast)
Datum:

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

Autor: Jemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
// Grafikbereich im Speicher 768 - 8192
  GLCD_Daten  (0x00);    // Grapic home address (low)
  GLCD_Daten  (0x03);    // ...(high)
  GLCD_Befehl (0x42);    // ...

  GLCD_Daten  (0x1E);    // Graphic area set (low)
  GLCD_Daten  (0x00);    // ...(high)
  GLCD_Befehl (0x43);    // ...

// Text Bereich im Speicher 0-512
  GLCD_Daten  (0x00);    // Text home adress (low)
  GLCD_Daten  (0x00);    // ...(high)
  GLCD_Befehl (0x40);    // ...

  GLCD_Daten  (0x1E);    // Text area set (low)
  GLCD_Daten  (0x00);    // ...(high)
  GLCD_Befehl (0x41);    // ...

Autor: Jemand (Gast)
Datum:

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

Autor: spess53 (Gast)
Datum:

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

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

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

GLCD_Daten  (0x00);    // Grapic home address (low)
GLCD_Daten  (0x03);    // ...(high)
..

GLCD_Daten  (0x1E);    // Graphic area set (low)
GLCD_Daten  (0x00);    // ...(high)
..

GLCD_Daten  (0x00);    // Text home adress (low)
GLCD_Daten  (0x00);    // ...(high)
..

GLCD_Daten  (0x1E);    // Text area set (low)
GLCD_Daten  (0x00);    // ...(high)
..

Und ich habe jetzt mal wie folgt versucht das Display zu löschen indem 
ich den ganzen Speicher mit 0en fülle:
void Speicher_Loeschen(void)
{
  unsigned int i;

  Speicher_Adresse(0x0000);

  for(i=0; i<(0xFFFF); i++)
  {
       GLCD_Daten(0);
    } 
  GLCD_Position(1,1);
}

void Speicher_Adresse (unsigned int Adresse)
{
  GLCD_Daten(Adresse%256);
  GLCD_Daten(Adresse>>8);
  GLCD_Befehl(0x24);
}

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

Autor: spess53 (Gast)
Datum:

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

Autor: Jemand (Gast)
Datum:

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

Autor: Ralf (Gast)
Datum:

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

Ralf

Autor: chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Jemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
// 0x0000 = 0
  GLCD_Daten  (0x00);    // Grapic home address (low)
  GLCD_Daten  (0x00);    // ...(high)
  GLCD_Befehl (0x42);    // ...

  GLCD_Daten  (0x1E);    // Graphic area set (low)
  GLCD_Daten  (0x00);    // ...(high)
  GLCD_Befehl (0x43);    // ...

// 0x1700 = 5888
  GLCD_Daten  (0x00);    // Text home adress (low)
  GLCD_Daten  (0x17);    // ...(high)
  GLCD_Befehl (0x40);    // ...

  GLCD_Daten  (0x1E);    // Text area set (low)
  GLCD_Daten  (0x00);    // ...(high)
  GLCD_Befehl (0x41);    // ...

// Weiteres
  GLCD_Befehl (0x80);    // Mode set (OR)
  GLCD_Befehl (0x9C);    // Display mode (Grafik und Text)


  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:
void Grafik_Speicher_Loeschen(void)
{
  unsigned int i;

  Speicher_Adresse(0x0000);

  for(i=0; i<(0x16FF); i++)
  {
       GLCD_Daten(0);
    } 
  GLCD_Position(1,1);
}
void Text_Speicher_Loeschen(void)
{
  unsigned int i;

  Speicher_Adresse(0x1700);

  for(i=0x1700; i<(0xFFFF); i++)
  {
       GLCD_Daten(0);
    } 
  GLCD_Position(1,1);
}

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.
void Speicher_Adresse (unsigned int Adresse)
{
  unsigned char Low;
  unsigned char High;

  Low = Adresse&255;
  Adresse=Adresse>>8;
  High = Adresse&255;
  
  GLCD_Daten(Low);
  GLCD_Daten(High);
  GLCD_Befehl(0x24);
}

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

Das verstehe ich nicht, was meinst du damit?

Nabend

Autor: Jemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Jemand (Gast)
Datum:

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

Autor: Jemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dass der C18 hier wieder irgendwas krankes optimiert?
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:
ADR=1904;

Autor: gerd (Gast)
Datum:

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

Autor: Jemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ne, char ist 8 Bit. Int(eger) ist 16 Bit.

Autor: gerd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welcher Compiler?

- gerd

Autor: Jemand (Gast)
Datum:

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

Also das hier funktioniert nicht:
Pixel_setzten(64,120);

void Pixel_setzten(unsigned char X, unsigned char Y)
{
unsigned int ADR;    // Zur Berechnung der RAM Adresse
ADR = 0;      // Die Grafik Home Adresse

if ( (X>128) | (Y>240) )   // Wenn der adressierte Bereich
{        // außerhalb des Displays liegt,
  return;      // dann springe sofort zurück!
}  

ADR = ((X-1)*30)+((Y-1)/8);  
ADR = 1904;

Speicher_Adresse(ADR);
Busy_Abfrage();      // Nachfragen ob das Display fertig ist

GLCD_Befehl (0xF8+1);            
}

Das dann schon:
Pixel_setzten(64,120);

void Pixel_setzten(unsigned char X, unsigned char Y)
{
unsigned int ADR;    // Zur Berechnung der RAM Adresse
ADR = 0;      // Die Grafik Home Adresse

if ( (X>128) | (Y>240) )   // Wenn der adressierte Bereich
{        // außerhalb des Displays liegt,
  return;      // dann springe sofort zurück!
}  

ADR = ((X-1)*30)+((Y-1)/8);  
ADR = 1904;  <--------------------------------------

Speicher_Adresse(ADR);
Busy_Abfrage();      // Nachfragen ob das Display fertig ist

GLCD_Befehl (0xF8+1);            
}

Aber warum denn?

Autor: Jemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry wegen Doppelpost!

Compiler C18 (Microchip)

Autor: Jemand (Gast)
Datum:

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

Autor: gerd (Gast)
Datum:

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

Autor: gerd (Gast)
Datum:

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

Autor: Jemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das macht Sinn. Dankeschön gerd!

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

Bewertung
0 lesenswert
nicht lesenswert
So nun habe ich das Display im Griff.

Autor: Spess53 (Gast)
Datum:

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

Autor: Jemand (Gast)
Datum:

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

Autor: Spess53 (Gast)
Datum:

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

Autor: Jemand (Gast)
Datum:

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

Autor: Spess53 (Gast)
Datum:

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

Autor: Jemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja gut. Ich fange gerade erstmal an das Teil ein wenig zu verstehen ^^

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.