Forum: Mikrocontroller und Digitale Elektronik Frage zu Display-Code


von Hannes (Gast)


Lesenswert?

Hey

Bin gerade beim Ansteuern eines Graphikdisplays 128x64 und habe ein 
fertiges glcd.c als Vorlage für genau den gleichen Controller.
Versuche nun einen Punkt auf das LCD zu schreiben, was auch zwar nicht 
100%ig funktioniert (Pixel hüpft hin und her), aber da bin ich dran.
Im Originalcode gibt es da eine Codepassage, die ich nicht ganz 
verstehe.
Festgelegt wird die Stelle des Punktes am Display:

LcdInstructionWrite (X_ADRESS + (Yaxis / 8));
LcdInstructionWrite (Y_ADRESS + (Xaxis);
LcdDataWrite (DataRead | (1 << (Yaxis % 8)));

Warum nehme ich bei der X-Adresse den Wert der Y-Koordinate und 
umgekehrt?

hannes

von Karl H. (kbuchegg)


Lesenswert?

Hannes schrieb:

> Festgelegt wird die Stelle des Punktes am Display:
>
> LcdInstructionWrite (X_ADRESS + (Yaxis / 8));
> LcdInstructionWrite (Y_ADRESS + (Xaxis);
> LcdDataWrite (DataRead | (1 << (Yaxis % 8)));
>
> Warum nehme ich bei der X-Adresse den Wert der Y-Koordinate und
> umgekehrt?

Sieht so aus, als ob da eine logische 90° Drehung des Displays mit 
eingebaut wurde. Vielleicht ist es auch im Datenblatt des Displays so 
bezeichnet, dass X und Y vertauscht sind. Vielleicht hatte deine Vorlage 
auch einen Fehler in der Achsbezeichnung, der zwar behoben aber nicht 
konsequent durchgezogen behoben wurde.

von Hannes (Gast)


Lesenswert?

Danke erstmal.
Beim Controller handelt es sich um den KS108, wobei ich im Datenblatt 
keinen Hinweis auf die 90°-Drehung gefunden habe. Außerdem stimmt die 
Anzeige am Display, denn wenn ich die Koordinaten vertausche, dann ist 
der Punkt komplett woanders.

Und warum nehme ich beim lcdDataWrite dann wieder nur die Y-Achse und 
nicht auch die X-Achse?

hannes

von Oliver (Gast)


Lesenswert?

Im allgemeinen hat sich der Ansatz "Im Datenblatt nachsehen" bei solchen 
und ähnlichen Problemen ziemlich bewährt ;-)

Da sollte alles notwendige drinnstehen.

Oliver

von Hannes (Gast)


Lesenswert?

Habe grade die Definition in einem Beispielprogramm gefunden.
Die Koordinaten sind wirklich vertauscht.

Dankeschön nochmal.

hannes

von Karl H. (kbuchegg)


Lesenswert?

Hannes schrieb:
> Danke erstmal.
> Beim Controller handelt es sich um den KS108, wobei ich im Datenblatt
> keinen Hinweis auf die 90°-Drehung gefunden habe.

Nein. Das hast du misverstanden.
Viellicht hat sich derjenige, von dem du den Code geklaut hast, eine 90° 
Drehung eingebaut (was weiß ich, weil ihm zb die Anschlüsse beim Einbau 
in ein Gehäuse im Weg waren, oder so was ähnliches)

von Oliver (Gast)


Lesenswert?

>Beim Controller handelt es sich um den KS108

Die Info kam etwas zu spät.

Der KS108 addressiert den 64x64-Bildschirm über acht 8-Bit hohe Zeilen 
(X=0..7) á 64 Bit (Y=0..63). Damit sind in dessen Konvention X und Y 
gegenüber der üblichen Anordnung vertauscht. Dein Code berücksichtigt 
das.

Das steht aber wirklich alles im Datenblatt ;-)

Oliver

von Tom M. (tomm) Benutzerseite


Lesenswert?

Hannes schrieb:
> Beim Controller handelt es sich um den KS108, wobei ich im Datenblatt
> keinen Hinweis auf die 90°-Drehung gefunden habe. Außerdem stimmt die
> Anzeige am Display, denn wenn ich die Koordinaten vertausche, dann ist
> der Punkt komplett woanders.

Da ist auch nix mit Drehung...

Die Horizontale wird tatsächlich als "Y" bezeichnet, siehe 
"Instuctions".

> Und warum nehme ich beim lcdDataWrite dann wieder nur die Y-Achse und
> nicht auch die X-Achse?

Nicht verwirren lassen... Was für dich X ist lt. Datenblatt Y.

von Hannes (Gast)


Lesenswert?

Was jetzt aber immer noch nicht passt, ist, dass wenn ich die Startzeile 
(Z-Addresse) auf 0 setzten will, also an den Anfang des Displays, der 
Punkt flackert. Es leuchtet nicht nur ein Pixel sondern in kurzen 
abwechselnden Abständen beide.
Woran liegt das wieder?

hannes

von Oliver (Gast)


Lesenswert?

>Woran liegt das wieder?

Am Code?

Oliver

von Hannes (Gast)


Angehängte Dateien:

Lesenswert?

So, der Code jetzt hinzugefügt.
Fast alle Probleme sind beseitigt, bis auf eines:

In der Funktion lcdSetDot() ist vor dem dataRead() ein 
lcdInstructionWrite(Y).
Dieses setzt mir den Datenport PORTD des Displays auf 0x40. Eben um auf 
die erste Spalte zuzugreifen. Wenn ich jetzt dataRead() aufrufe, gibt 
mir das natürlich 0x40 zurück, was aber nicht sein soll. Denn beim 
ersten Durchlauf steht am Display ja noch nichts.
Wenn ich den Port jetzt vorher auf 0x00 setze, bekomme ich keine 
vertikale Linie zusammen, sondern immer nur einen Punkt pro Spalte.
In meiner Vorlage ist es genauso programmiert, deswegen bin ich jetzt 
ein wenig ratlos.
Kann da wer weiterhelfen?

hannes

von Oliver (Gast)


Lesenswert?

>Wenn ich jetzt dataRead() aufrufe, gibt
>mir das natürlich 0x40 zurück, ...

Datenblatt lesen. Code lesen. POPRTC und PORTD mit #defines lesbare 
Namen geben.

Der Display-Befehl "Read display data" liest das Display an der 
aktuellen Leseadresse aus. Wenn das Display leer ist, sollte da immer 
0x00 gelesen werden. Was die aktuelle Leseadresse ist, und warum man da 
zweimal lesen muß, steht auch im Datenblatt.

Oliver

von Hannes (Gast)


Lesenswert?

Das mit dem Dummy-Read und der Leseaddresse habe ich schon gefunden im 
Datenblatt. Das macht mir auch keine Sorgen mehr.

Aber nur rein von der Logik her, wenn ich eine Instruction auf den PORTD 
ausgebe, und im nächsten Schritt diesen wieder einlese, ohne den Port zu 
löschen, dann ist doch das jeweilige Bit noch gesetzt.
Ich habe es jetzt so gelöst, das ich auf dataRead() verzichte und 
stattdessen meinen Befehl direkt nach dem lcdDataWrite() noch auf eine 
Variable schreibe. Diese simuliert mir also den dataRead.

Trotzdem möchte ich wissen, wie ich das Problem umgehen kann.

hannes

von Karl H. (kbuchegg)


Lesenswert?

Hannes schrieb:

> Trotzdem möchte ich wissen, wie ich das Problem umgehen kann.

Da liegt anscheinend einiges im argen.
Ich habe jetzt nicht grossartig analysiert, aber zb das hier

void lcdWaitBusy()
{
  PORTD = 0xff;

  unsigned char read;

  read = PORTD;


  PORTC = 0b00000000;


  triggerH;
  lcdDelay(1);
  triggerL;

  while(read & 0x7f == 0x80);
}

Das ist doch Müll
* Von einem Pin wird eingelesen, indem man das PIN Register ausliest?
* Wie soll sich in der while Schleife ganz unten, die Variable read
  jemals verändern?

Aber da du an dieser Stelle schon DEN Fehler machst, einen Port 
einzulesen indem du das PORT Register liest, denke ich, dass du den 
Fehler auch an anderen Stellen gemacht hast.

von Hannes (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> hler machst, einen Port
> einzulesen indem du das PORT Register liest

Wie mach ichs denn dann richtig?

hannes

von Oliver (Gast)


Lesenswert?

In der Codesammlung gibt es einige gut funktionierende libs für den 
KS0108. z.B. diese hier:
Beitrag "KS0108 GLCD Routinen"

Oliver

von Hannes (Gast)


Lesenswert?

Theoretisch würds ja so funktionieren:

DDRD = 0x00; //setzt mir PORTD als Eingang.
read = PORTD;

oder eben gleich PIND einlesen

read = PIND;

So entnehme ich das dem Datenblatt des ATMega8.

hannes

von Karl H. (kbuchegg)


Lesenswert?

Hannes schrieb:
> Theoretisch würds ja so funktionieren:
>
> DDRD = 0x00; //setzt mir PORTD als Eingang.
> read = PORTD;
>
> oder eben gleich PIND einlesen
>
> read = PIND;
>
> So entnehme ich das dem Datenblatt des ATMega8.

Dann liest du falsch.
Arbeite bitte die ersten Kapitel im Tutorial durch.

Zwischen den beiden gibt es einen grundlegenden Unterschied. Vor allen 
Dingen, weil das Auslesen von PORT etwas völlig anderes macht als du 
vermutest (du liest damit den Einschaltzustand der Pullup-Widerstände 
aus). Den Zustand der physikalischen Pins erhält man, indem man das PIN 
Register ausliest. Punkt.

von Hannes (Gast)


Lesenswert?

Ok, danke. Werd ich mich mal dran machen.

hannes

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.