PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Samsung LCD 2138A macht Cursorprobleme wenn CGRAM geschr



Khan
10.02.2009, 19:59
Hallo Zusammen,

also ich komme wirklich nicht merh weiter. Scheitere schon seit 3 Wochen. ](*,)

vorweg, ich habe ATmega8+STK500+Samsung LCD 2138A (m50530)

Mein Problem ist:

http://lcd-linux.sourceforge.net/pdfdocs/M50530.pdf

Möchte große eigene Zeichen in den CGRAM schreiben, habe auch geschaft.
Allerdings seit ich dies gemacht habe setzt sich mein Kursor (aus mir
unerklerlichen Gründen) völlig an andere Stelle auf dem LCD.

z.B:
LCD_setCursorPos(2,0); // Setze kursor 3.Zeile Spalte 0
LCD_write("abcd"); // schreibe abcd

aber er schreibt mitte 7. zeile...

Mein CGRAM Kapazität soll 64Word sein --> kursor adresse 0xC0
Und der 1.Zeichen ist mit 0xF8 auszulesen. Siehe S.14
Damit dies so funktioniert habe ich beim initialisieren als (S.27) WD
0xDa
eingeben müssen. Mit 0xD8 funktioniert es aber kann halt nicht in CGRAM
schreiben.
// DB7, DB6, DB4, DB3 0xDA = 11011010 //0xD8 = 216 = 11011000
LCD_sendByte(0xDA, 0); //Set function mode (8Bit, 5x7 Character)

Ich hoffe dies alles ist aussagekräftik.

Ich bin wirklich ein wenig verzweifelt!
Bitte um Hilfe...

Grüße Khan

ragnar
10.02.2009, 23:35
1. Auf welche Routinen beziehst du dich da ?
LCD-Linux unterstützt kein m50530 sondern nur hd47780.
Am besten posten.

2. Welches Display genau ? 8x24 ?

3. Was genau möchtest du tun ?
Font auf von 8x5 auf 12x5 Pixel stellen ?
Und dann noch eigene Zeichen definieren ? (in 11x5) ?

4. Speicherkapazität von 64 ist glaube ich richtig.
Das hieße das erste Zeichen wäre an 0xC0, danach alle 8 bzw 16
Bytes das nächste Zeichen, je nach Font. Bei 0xF8 fängt also auch
ein Zeichen an (8x5 Font).

5. Ich komme mit deinen Befehlen nicht zurecht. Bitte schreib
mal _genau_ welche Befehle mit welchen Parametern du alle
absetzt.

Ragnar

Khan
11.02.2009, 09:00
Hallo und danke für dein Antwort.

also zum 1.:
Ich beziehe mich auf die Routine LCD_init ().(in lcd_m50530.c)
Ich habe nicht mit LCD-Linux gearbeitet, weis auch nicht was das ist.
Arbeite grad in Windows.

zu 2.:
hast richtig geraten. 8x24

zu 3.:
Fonts 5x8Pixel sollen bleiben.
Eigene Zeichen sind ebenfalls 5x8 Pixel-Zeichen (wie im Funktion xxx() )

zu 4.:
Genau so wie du sagst habe(besser versucht) ich auch programmiert.

zu 5.:
LCD_setCursorPos (y,x); // Setzt cursor mit y auf die Zeile und mit x auf die Spalte
LCD_writeChar ('a'); // schreibt einen Char
LCD_write ("String"); // schreibt eine String
LCD_writeChar (0xF8); //schreibt den ersten slbst. definierten Zeichen auf die LCD

dass zu den einfachen Befehlen.

Jetzt die Init Routine:





void LCD_init(void)
{
LCD_waitReady (); // Wartet bis LCD bereit
// alle Leitungen auf Ausgang schalten
LCD_DDR = 0xFF;
//LCD_sendByte(0b100011, 0); // SD:
// auf 4-Bit-Mode umschalten
/*
SET FUNCTION MODE
input:
OC1 0
OC2 0
RW 0
DB7,DB6 1
DB5 I/O 8/4 (1 = 8 bit, 0 = 4 bit)
DB4 FONT 8/12 (1 = 5x8 fonts, 0 = 5x12 fonts)
DB3,DB2 DUTY DT1 = 1; DT2 = 0;
DB1,DB0 RAM RA1 = 1; RA2 = 0;
*/
LCD_sendByte(0xDA, 0); //SF: Siehe komentar oben
LCD_waitReady (); // Wartet bis LCD bereit
LCD_sendByte(0x50, 0); //SE: Incrementiere den Curs. nach write data (WD), und No change display start adr.
LCD_waitReady (); // wartet wieder
LCD_sendByte(0x30, 0); //SD: Set disp. mode && Display on
LCD_clear(); //löscht lcd
xxx (); /* Schreibt selbst definierte Zeichen in CGRAM */
}


Das habe ich laut Datenblat erstellt. (von S. 25 bis 32)

ich hoffe dass ist Aussagekräfig.
Wenn nicht, sende ich dir natürlich mehr Informationen!


Ich will eigentlich dass Gleiche wie auf dem Bild im Anhang DisplayTest_8x24_2.jpg


grüße

ragnar
11.02.2009, 21:01
Hi,

Entschuldigung für meine zahlreichen Nachfragen gestern, Ich hatte nicht gesehen, daß du deinen (fast) kompletten Code angehängt hast.

Folgendes ist mir aufgefallen:

LCD_init(void) ist IMHO so in Ordnung.

In write_cgram() steht folgendes


LCD_setCursorAddress( adresse + (8*index));
for ( i = 0; i < 8 ; i++) {
LCD_writeChar( pixels[i]);
LCD_setCursorAddress( adresse + (8*index) + i);
}


IMHO müsste da stehen:


for ( i = 0; i < 8 ; i++) {
LCD_setCursorAddress( adresse + (8*index) + i);
LCD_writeChar( pixels[i]);
}


Eventuell nach jedem Befehl an das LCD noch ein LCD_waitReady(),
genauso wie im init. Die Befehle brauchen auch auf Displayseite
etwas zum ausführen.

Warum am Ende von write_cgram() ein LCD_clear() ?
Das ist IMHO nicht notwendig.

Ansonsten scheint mir xxx() soweit zu stimmen.


Insgesamt sollte das so funktionieren.
Bitte probier die obigen Vorschläge aus.


Wenn das nicht klappt folgendes probieren:
- die initialisierung ganz ohne xxx() ausführen
- mit xxx, aber nur ein selbstdefiniertes Zeichen, möglichst aus der Mitte
- langsam alle Zeichen dazunehmen
Und dann nach jedem Schritt ausprobieren, ob das Fehlerbild noch auftritt.

Zum Fehlerbild fällt mir nur folgendes ein: Es könnte sein, daß deine 'Display Start Address' verschoben ist. Im Zweifelsfall das Display
ausgehend von LCD_setCursorPos(0,0) mit den Zeichen a-zA-Z0-9 vollschreiben und schauen ob sich ein Muster ergibt.


Ragnar

Khan
13.02.2009, 08:17
Hallo Ragnar,

also ich habe alles so versucht wie du beschrieben hast.
Aber immer dass gleiche Effekt.

Es mus was total einfaches oder banales sein!
Denn sonst hätte ich es gefunden ;-)

Ich habe auch einen ganz langen String geschrieben, im Anhang ist ein Bild davon. (a-z,A-B,0-9) an die Position LCD_setCursorPos (0,0);

Kann es sein dass wenn ich die Ram Adresse für den CGRAM aktiviere/reserviere dass die Adressierung für Cursorpositionierung auch ändert?
Hier mal das Code dazu:








// setzt den Cursor an die angegebene Position (y = Zeile, x = Spalte)
void LCD_setCursorPos(const unsigned char y, const unsigned char x)
{
// Adresse aus x und y berechnen
// Adressen sind wie folgt: Zeile 0 = 0; Zeile 1 = 64; Zeile 2 = 128; Zeile 3 = 192; Zeile 4 = 0+24; Zeile 5 = 64+24; Zeile 6 = 128+24; Zeile 7 = 192+24
unsigned char address = x + ((y % 4) << 6);
if (y > 3)
address += 24;
LCD_sendByte(address, (1<<LCD_OC1_PIN) | (1<<LCD_OC2_PIN));
}


Set Function: u.a. Adressierung des CGRAM


// auf 4-Bit-Mode umschalten
/*
SET FUNCTION MODE
input:
OC1 0
OC2 0
RW 0
DB7,DB6 1
DB5 I/O 8/4 (1 = 8 bit, 0 = 4 bit)
DB4 FONT 8/12 (1 = 5x8 fonts, 0 = 5x12 fonts)
DB3,DB2 DUTY
DB1,DB0 RAM
*/
LCD_sendByte(0xDA, 0); // DB7, DB6, DB4, DB3



grüße
Khan[/code]

Khan
13.02.2009, 09:49
Hallo Ragnar,

also habe mal weitergelesen und "glaube" den Fehler eingegrenzt zu haben.
Auf dem Datenblatt Seite 6 Steht, wenn man den CGRAM adressiert, ändert sich der Characterbereich(siehe Tabelle.)
http://lcd-linux.sourceforge.net/pdfdocs/M50530.pdf

Wenn es dieser sein kann, kann ich dann überhaubt mein ganzes LCD Bereich voll ausnutzen?
Denn laut Tabelle 3 auf Seite 6 ist für:

RA1 = 0
RA0 = 0
Sprich 4-Line Display 0x00 bis 0x3F also sind es 0- 63 Zeichen.
Deckt mein ganzes LCD.

Wenn ich aber den CGRAM Benützen und weiterhin 4-Line Disp. haben will
wird logischerweise:
RA1 = 1
RA0 = 0 sein.
Somit adressiere ich für 192 Wörter nur 0x00 bis 0x2F, das sind 47 Character also 16 weiniger. Passt zu meiner Fehlerbid. Sind um 16 Zeichen Verschoben.

Wie kann ich aber dies übergehen/lösen?

Grüßen

Khan
13.02.2009, 10:57
Hallo,

also jetzt geht es! =D>
Kollege hat mir geholfen.

Das Problem lag wie ich vermutete in der Routine LCD_setCursorPos(y,x);

Es funktioniert zwar aber ich weis nicht warum :-k
Verstehst du es vielleicht?

er hat nur dass geändert
address += 88;
// address += 24;

Hier der funktionierende Code:


// setzt den Cursor an die angegebene Position (y = Zeile, x = Spalte)
void LCD_setCursorPos(const unsigned char y, const unsigned char x)
{
// Adresse aus x und y berechnen
// Adressen sind wie folgt: Zeile 0 = 0; Zeile 1 = 64; Zeile 2 = 128; Zeile 3 = 192; Zeile 4 = 0+24; Zeile 5 = 64+24; Zeile 6 = 128+24; Zeile 7 = 192+24
// unsigned char address = x + ((y % 4) << 6);
unsigned char address = x + y * 48;
if (y > 3)
address += 88;
// address += 24;
LCD_sendByte(address, (1<<LCD_OC1_PIN) | (1<<LCD_OC2_PIN));
}

ragnar
14.02.2009, 20:12
Hallo Khan,

Ich kann nur anhand deines Codes vermuten was passiert ist:

1.) Du hast den bisherige Code mit mit RA1=0 und RA0=0 entwickelt.
Das heißt du hast das Display mit 4 Zeilen á 64 Zeichen initialisiert.
Das entspricht nicht den realen Gegebenheiten, funktioniert aber
vermutlich trotzdem.

Jede Zeile hat damit im Controller 64 Bytes, der DDRAM ist komplett
aufgeteilt. Von den 64 Bytes zeigt das Display allerdings nur 48 an,
16 Bytes sind "verloren".

Das spiegelt sich direkt in SetCursorPos() wieder. Die zweite Zeile
beginnt z.B. bei Adresse 64 im Speicher, SetCursorPos() setzt den
Cursor also an diese Stelle.

2.) Zur Nutzung des CGRAMs hast du den Controller plötzlich mit
RA1=1, RA0=0 initialisiert. Das ist schon der grundlegende Fehler.
Dadurch ist der Speicher anders aufgeteilt. Das DDRAM ist jetzt in
Zeilen mit je 48 Zeichen aufgeteilt (die natürlich direkt
hintereinanderliegen).

Schreibt jetzt also dein setCursorPos() an den Anfang der 3. Zeile
so wird der Cursor weiterhin an Speicheradresse 64 gesetzt. Durch
die geänderte Speicheraufteilung ist das aber nicht mehr der Anfang
der 2. Zeile sondern das 16. Zeichen der 2. Zeile (64-48 ).

Zur neuen Cursorberechnung deines Kollegen (nicht nur +=88, genau hinschauen):

Für Zeile 0..3 gilt folgende Formel:


x + y*48


Für Zeile 4..7 gilt folgende Formel:


x + (y-4)*48 + 24 = x + y*48 - 4*48 + 24


Wird statt der Formel 4..7 die Formel 0..3 verwendet ergibt sich folgende Differenz:


[0..3] - [4..7] = x + y*48 - x - y*48 + 4*48 - 24 = 4*48 - 24 = 168.


Ist die Zeile also 4..7 muß von der Formel 0..3 nochmal 168 abgezogen werden. Da die Variable in C nur 8 Byte groß deklariert ist kann man statt 168 abzuziehen auch (256-168)=88 dazuaddieren (durch Überlauf).


Ragnar