- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 8 von 8

Thema: Samsung LCD 2138A macht Cursorprobleme wenn CGRAM geschr

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    10.12.2007
    Beiträge
    18

    Samsung LCD 2138A macht Cursorprobleme wenn CGRAM geschr

    Anzeige

    Powerstation Test
    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
    Angehängte Dateien Angehängte Dateien

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    23.06.2005
    Ort
    München
    Beiträge
    113
    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

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    10.12.2007
    Beiträge
    18
    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 (0xF; //schreibt den ersten slbst. definierten Zeichen auf die LCD

    dass zu den einfachen Befehlen.

    Jetzt die Init Routine:



    Code:
    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
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken displaytest_8x24_2.jpg  
    Angehängte Dateien Angehängte Dateien

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    23.06.2005
    Ort
    München
    Beiträge
    113
    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
    Code:
        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:
    Code:
        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

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    10.12.2007
    Beiträge
    18
    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:






    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);
    	if (y > 3)
    		address += 24;
    	LCD_sendByte(address, (1<<LCD_OC1_PIN) | (1<<LCD_OC2_PIN));
    }
    Set Function: u.a. Adressierung des CGRAM
    Code:
    	// 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]
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken dsc00294_137.jpg  

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    10.12.2007
    Beiträge
    18
    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

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    10.12.2007
    Beiträge
    18
    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
    Verstehst du es vielleicht?

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

    Hier der funktionierende Code:
    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));
    }

  8. #8
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    23.06.2005
    Ort
    München
    Beiträge
    113
    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:
    Code:
    x + y*48
    Für Zeile 4..7 gilt folgende Formel:
    Code:
    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:
    Code:
    [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-16=88 dazuaddieren (durch Überlauf).


    Ragnar

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen