Forum: Mikrocontroller und Digitale Elektronik [KS0108] Probleme beim Lesen der Daten von Spalte 63 und 127


von Philipp D. (phili)


Lesenswert?

Liebe Forum-Gemeinde,
ich nutze die LCD Bibliothek von Pascal Stang um ein LCD Display mit 
128x64 Pixeln und einem KS0108 Controller anzusprechen.

Wenn man nun über die Routine "lcd_SetDot" ein Pixel setzten möchte, so 
klappt dies bei mir prima, so lange ich nicht in die letzten Spalten 
eines der beiden Controller (Display ist ja aus zwei 64x64 Flächen 
zusammengestellt) schreiben will.

Es scheint, als ob der Controller beim Lesen der Inhalte in diesen 
Spalten über
1
 temp = lcd_DataRead();

immer 0x00 zurückliefert und deshalb über
1
 lcd_DataWrite(temp & ~(1 << (y % 8)));

immer nur ein Pixel in diesen beiden Spalten
gesetzt werden kann.

Kann jemand dieses Verhalten bestätigen? Bei den anderen Spalten geht es 
wie gewüscht.

Gute Nacht
Phili

von Philipp D. (phili)


Lesenswert?

So nun habe ich die "lcd_SetDot" erweitert und nun läuft es:
1
void lcd_SetDot(uint8_t x, uint8_t y)
2
{
3
  uint8_t temp;
4
5
  lcd_SetAddress(x, y/8);
6
  temp = lcd_DataRead();  // dummy read
7
  lcd_SetAddress(x, y/8);
8
  temp = lcd_DataRead();  // read back current value
9
  lcd_SetAddress(x, y/8);
10
  lcd_DataWrite(temp | (1 << (y % 8)));
11
12
  lcd_StartLine(0);
13
}

Der ursprüngliche Code lautete
1
void lcd_SetDot(uint8_t x, uint8_t y)
2
{
3
  uint8_t temp;
4
5
  lcd_SetAddress(x, y/8);
6
  temp = lcd_DataRead();  // dummy read
7
  temp = lcd_DataRead();  // read back current value
8
  lcd_SetAddress(x, y/8);
9
  lcd_DataWrite(temp | (1 << (y % 8)));
10
11
  lcd_StartLine(0);
12
}
Ich verstehe nur nicht, warum dasHinzufügen von
1
  lcd_SetAddress(x, y/8);
das Problem löst und warum es nur beim Schreiben (bzw. Auslesen) der 
letzten Spalten eines Conrollers auftritt.

Vielleicht noch nen Tipp dazu von jemandem?

Phili

von Oliver (Gast)


Lesenswert?

Normalerweise kommen die meisten Probleme mit LCD's von falschem (zu 
schnellem) Timing.
Wie du schon selber sagtest, es gibt eigentlich keinen Grund, warum die 
Ursprungsvarinte nicht funktionieren sollte. Ich kenne jetzt die lib von 
Pascal Stang nicht, und ob die das busy-flag abfragt, oder nicht, aber 
irgendwo da drin wird es auch entsprechenden delays geben. Was passiert, 
wenn du die mal verlängerst?

Oliver

von Philipp D. (phili)


Lesenswert?

Hallo Oliver

> Normalerweise kommen die meisten Probleme mit LCD's von falschem (zu
> schnellem) Timing.
> Wie du schon selber sagtest, es gibt eigentlich keinen Grund, warum die
> Ursprungsvarinte nicht funktionieren sollte. Ich kenne jetzt die lib von
> Pascal Stang nicht, und ob die das busy-flag abfragt,

Das Busy-Flag wird von den Bibliotheksroutinen abgefragt.

> oder nicht, aber irgendwo da drin wird es auch entsprechenden delays geben.

Habe das Display direkt in den extern I/O Memory gehängt und muß mich 
somit nicht mehr um die direkte Beschaltung der Leitungen kümmern. Die 
Waitstaites habe ich zwischenzeitlich auf die maximalen Werte gesetzt. 
Das hat aber auch nichts geändert.

Phili

von Hannes L. (hannes)


Lesenswert?

> und muß mich
> somit nicht mehr um die direkte Beschaltung der Leitungen kümmern

aha... - Und das geht?

Nein, ich habe keinen Tip, da mir Pascal fremd ist.

...

von Oliver (Gast)


Lesenswert?

Direkten Asnchluß ans memory-i/O hab ich noch nie gemacht, aber auch da 
muß das Timing eingehalten werden. Wie stellst du das denn sicher?

Im Code für Memory-IO der avrlib

http://www.mil.ufl.edu/~chrisarnold/components/microcontrollerBoard/AVR/avrlib/docs/html/index.html

finde ich, im Gegensatz zum Code für Port-IO, gar keine delays. Macht 
das alles die Hardware automatisch?

Oliver

von Philipp D. (phili)


Lesenswert?

Hallo Hannes, hallo Oliver,

> Direkten Asnchluß ans memory-i/O hab ich noch nie gemacht, aber auch da
> muß das Timing eingehalten werden. Wie stellst du das denn sicher?

Direkte Delays gibt es da wirklich nicht. Es wird habt über die 
Definition der Waitstates geregelt (z.B. Datenblatt Mega128 S. 31ff)

Ist sehr schick das spo zu machen, denn der Code für die harwarenahen 
Funktionen reduziert sich praktisch auf eine Zeile und zu 
programmierende Wackeln an den Steuerleitungen entfällt.

Für ein Command-Write sieht das dann ungefähr so aus
1
void ks0108WriteCommand(uint8_t cmd, uint8_t chip) {
2
    lcd_BusyWait(chip);    // wait until LCD not busy
3
    *(volatile unsigned char *) (LCD_CONTROLLER0_CTRL_ADDR + LCD_CONTROLLER_ADDR_OFFSET*chip + LCD_CONTROLLER_WRITE) = cmd;
4
 }
mit
1
void lcd_BusyWait(uint8_t controller)
2
{
3
  // wait until LCD busy bit goes to zero
4
  while(*(volatile unsigned char *) (LCD_CONTROLLER0_CTRL_ADDR + LCD_CONTROLLER_ADDR_OFFSET*controller + LCD_CONTROLLER_READ) & LCD_STATUS_BUSY);
5
}

P.S. Habe gerade die Lib gewechselt. Nutze jetzt die von Maximilian 
Thiele, weil dort die Textausgabe an beliebigen Pixeln direkt 
implementiert ist. Die Umsetzung des direkten I/O Memoryzugriffs ist 
noch ein wenig buggy. Mal sehen, was hier aus meinem ursprünglichen 
Problem geworden ist.

Phili

von Oliver (Gast)


Lesenswert?

Na dann, wenn alles sonst richtig ist, hat vielleicht das LCD eine 
Macke.

Spasseshalber kannst du ja mal in
1
  temp = lcd_DataRead();  // dummy read
2
  lcd_SetAddress(x, y/8);
3
  temp = lcd_DataRead();  // read back current value

das hinzugefügte lcd_SetAddress(x, y/8) durch ein einfaches delay 
gleicher Länge ersetzen, und schauen, ob das auch funktioniert.

Oliver

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.