Forum: Mikrocontroller und Digitale Elektronik LCD eigene Zeichen


von Lokus P. (derschatten)


Lesenswert?

Das Thema wurde hier ja zwar schon mehrmals angesprochen, hab aber 
trotzdem leider nichts passendes gefunden.
Habe jetzt 2 Stunden so ziemlich jeden beitrag durchgeackert und auch 
Google befragt, konnta aber keine hilfreiche Anleitung finden wie man 
die 8 frei definierten Zeichen für ein LCD programmiert.

Soviel ich herausfinden konnte geht das ganze mittels einer Tabelle, in 
der man seine Pixel definiert.

Mit einer Funktion definiert man dann in welche Adresse des Displays 
welches Zeichen geschrieben wird
1
void write_lcd_cg(byte lcd_addr, byte *lcd_zeichen)
2
{
3
  byte lcd_i;
4
  for(lcd_i = 0; lcd_i < 8; lcd_i++)
5
  {
6
    lcd_puts(0x40 + lcd_addr * 8 + lcd_i,1); // CG RAM Adresse Set (01aa azzz)
7
    lcd_puts(*lcd_zeichen,0);  // Data Write 8x Pixelzeile
8
    lcd_zeichen++;
9
  }
10
}
Und das gibt man dann irgendwie aus.

Nur komm ichd amit überhaupt nicht klar.
Ich verwende die LCD-Library von Peter Fleury.

von Plan (Gast)


Lesenswert?

Ich habe eine EADOG und mir eine eigene LIB geschrieben. Da schreibe ich 
sowas raus:
1
  // neues Zeichen:
2
  LCD_WR(0, 0x78);  // RAM Umschalten
3
  LCD_WR(1, 0x14);  // Zeichen Addr 7: "KHz"
4
  LCD_WR(1, 0x18);
5
  LCD_WR(1, 0x14);
6
  LCD_WR(1, 0x00);
7
  LCD_WR(1, 0x13);
8
  LCD_WR(1, 0x19);
9
  LCD_WR(1, 0x16);
10
  LCD_WR(1, 0x17);
11
  LCD_WR(0, 0x80);  // Zeichenanzeige wieder aktivieren

Mit
LCD_Char(7);  // LCD Zeichen "KHz"
rufe ich das Zeichen auf.

PS: Die Definition:
void LCD_WR(unsigned char RS, unsigned char Dat);
void LCD_Char(char Dat);

von komische idee (Gast)


Lesenswert?

im datenblatt gibt es startadressen  für die eigenen zeichen

 ab dieser startadresse werden 8 byte reingeschrieben
diese stellen die pixel dar

also

1. byte: xxx00000
2. byte: xxx00000
3. byte: xxx00000
4. byte: xxx00000
5. byte: xxx00000
6. byte: xxx00000
7. byte: xxx00000
8. byte: xxx00000

da es nur 5x8 pixel sind werden nur die untersten bits genutzt

aufrufen kann man das zeichen ganz einfach in dem man die normale 
lcd_puts( ) mit  0x00 bis 0x07  aufruft


grob nochmal ..

also ein array mit 8 byte die pixelweise das zeichen darstellen
const   char symbol[]  PROGMEM= {130,130,130,130,130,130,130,130};

das läd man ab adresse 0x40 in den RAM des LCDs
also ab
adresse 0x40  ( lcd_puts ( 0x00)  )
adresse 0x48  ( lcd_puts ( 0x01)  )
adresse 0x4F  ( lcd_puts ( 0x02)  )

von Lokus P. (derschatten)


Lesenswert?

Also das mit der Tabelle hab ich ja hinbekommen.
Das schreiben in den LCD-RAM ist mir noch nicht ganz klar.

Wie genau funktioniert das?

von Chris M. (shortie)


Lesenswert?

ich hab das so gelöst:
1
static const PROGMEM unsigned char cHddChar[] =  //  Acht selbstdefinierte Symbole fuer das LCD
2
{
3
  0x00, 0x0A, 0x1B, 0x1B, 0x18, 0x1F, 0x0E, 0x00,  // Uhrensymbol 3 Uhr
4
  0x00, 0x0A, 0x1B, 0x1B, 0x03, 0x1F, 0x0E, 0x00,  // Uhrensymbol 9 Uhr
5
  0x1F, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1F,  // Ein/Aus Symbol
6
  0x00, 0x0A, 0x1F, 0x1F, 0x1F, 0x0E, 0x04, 0x00,  // Herz
7
  0x15, 0x0E, 0x15, 0x0E, 0x04, 0x04, 0x04, 0x00,  // Sendeturm
8
  0x04, 0x0E, 0x1F, 0x11, 0x11, 0x11, 0x1F, 0x00,  // Haus
9
  0x04, 0x0E, 0x1F, 0x04, 0x04, 0x04, 0x04, 0x00,  // Pfeil nach oben
10
  0x04, 0x04, 0x04, 0x04, 0x1F, 0x0E, 0x04, 0x00    // Pfeil nach unten
11
//  0x0E, 0x1F, 0x0E, 0x11, 0x0E, 0x11, 0x0E, 0x00,    // Festplattensymbol
12
};

und in lcd_init nach dem Wechsel in den 4Bit-Modus kommt dann eine 
Schleife die die Zeichen ins Display überträgt:
1
    lcd_write (0x22,0);      //Init in 4 Bit Mode
2
    for(int i=0; i<64; i++)  // Die benutzerdefinierten Zeichen 
3
    {                        // in das Display schreiben
4
      lcd_write(i+64,0);     // 64 = 0x40 = CG-RAM Adresse 0
5
      lcd_write(pgm_read_byte_near(&cHddChar[i]),1);
6
    }
7
    lcd_write (0x80,0);      //Set DD-Ram Adresse = 0

von Lokus P. (derschatten)


Lesenswert?

Hi, das hatte ich schon versucht.

Kannst du mir sagen an welche Stelle genau die beiden Codeschnippsel hin 
müssen?
Ich nehme mal an beide ins die lcd.c

Und wie gibt man diese Zeichen dann aus?

von Chris M. (shortie)


Lesenswert?

ich hab das ganze in lcd.c drin - das ist richtig. Die Tabelle oben nach 
den #include Zeilen und der Rest in der Funktion lcd_init. Allerdings 
nutze ich die LCD-Routine von Ulrich Radig.

von Lokus P. (derschatten)


Lesenswert?

Ich habs jetzt mal so versucht:
1
static const unsigned char symbol[] PROGMEM =    // Acht selbstdefinierte Symbole fuer das LCD
2
{
3
  0x90, 0x98, 0x9C, 0x9E, 0x9C, 0x98, 0x90, 0x80,  //
4
  0x00, 0x0A, 0x1B, 0x1B, 0x03, 0x1F, 0x0E, 0x00,  //
5
  0x1F, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1F,  //
6
  0x00, 0x0A, 0x1F, 0x1F, 0x1F, 0x0E, 0x04, 0x00,  //
7
  0x15, 0x0E, 0x15, 0x0E, 0x04, 0x04, 0x04, 0x00,  //
8
  0x04, 0x0E, 0x1F, 0x11, 0x11, 0x11, 0x1F, 0x00,  //
9
  0x04, 0x0E, 0x1F, 0x04, 0x04, 0x04, 0x04, 0x00,  //
10
  0x04, 0x04, 0x04, 0x04, 0x1F, 0x0E, 0x04, 0x00  //
11
};

Und bei der Display Initialisierung dann:
1
    lcd_write(0x22,0);                  // Init in 4 Bit Mode
2
  for(int i=0; i<64; i++)
3
  {
4
    lcd_write(i+64,0);                // CG RAM Adresse Set (01aa azzz)
5
    lcd_write(pgm_read_byte_near(&symbol[i]),1);  // Data Write 8x Pixelzeile
6
  }
7
    lcd_write(0x80,0);                  // Set DD-Ram Adresse = 0

Wenn ich jetzt allerdings mit
1
  lcd_gotoxy(0,0);
2
  lcd_putc(0x00);
3
  lcd_gotoxy(1,0);
4
  lcd_putc(0x01);
5
  lcd_gotoxy(2,0);
6
  lcd_putc(0x02);
7
  lcd_gotoxy(3,0);
8
  lcd_putc(0x03);
9
  lcd_gotoxy(4,0);
10
  lcd_putc(0x04);
11
  lcd_gotoxy(5,0);
12
  lcd_putc(0x05);
13
  lcd_gotoxy(6,0);
14
  lcd_putc(0x06);
15
  lcd_gotoxy(7,0);
16
  lcd_putc(0x07);

meine Zeichen anzeigen möchte bekomme ich nur verstümmelte Symbole.

von Jens K. (jjk) Benutzerseite


Lesenswert?

Manfred W. schrieb:
> Ich habs jetzt mal so versucht:
>
>
1
> static const unsigned char symbol[] PROGMEM =    // Acht
2
> selbstdefinierte Symbole fuer das LCD
3
> {
4
>   0x90, 0x98, 0x9C, 0x9E, 0x9C, 0x98, 0x90, 0x80,  //
5
>   0x00, 0x0A, 0x1B, 0x1B, 0x03, 0x1F, 0x0E, 0x00,  //
6
>   0x1F, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1F,  //
7
>   0x00, 0x0A, 0x1F, 0x1F, 0x1F, 0x0E, 0x04, 0x00,  //
8
>   0x15, 0x0E, 0x15, 0x0E, 0x04, 0x04, 0x04, 0x00,  //
9
>   0x04, 0x0E, 0x1F, 0x11, 0x11, 0x11, 0x1F, 0x00,  //
10
>   0x04, 0x0E, 0x1F, 0x04, 0x04, 0x04, 0x04, 0x00,  //
11
>   0x04, 0x04, 0x04, 0x04, 0x1F, 0x0E, 0x04, 0x00  //
12
> };
13
>

Also das höchste was pro Zeile an Hex Wert geht ist 0x1F (alles an) ... 
wie kommen Deine 0x90 oder 0x98 zustande? Die 8 HEX Werte geben ja die 8 
Zeilen eines Zeichens an, mit jeweils 5 bit ...

Als kleine Hilfe fand ich diese Seite immer praktisch: 
http://www.quinapalus.com/hd44780udg.html

Mal damit mal Deine Zeichen und nimm das Ergebnis für den symbol[] ...

Gruß
 Jens

von Kay V. (kay1971)


Lesenswert?

Chris M. schrieb:
> nutze ich die LCD-Routine von Ulrich Radig.

Hallo Chris,

ich setzte dieselbe Routine ein und mir stellt sich jetzt noch die 
Frage, wie du die Zeichen aufrufst.
LCD_PRINT scheint je nur Ascii zu nehmen, wenn ich das richtig lese?

MfG
Kay

von Chris M. (shortie)


Lesenswert?

lcd_print nimmt auch andere Zeichen.
Hier mal ein Beispiel wie alle 8 Zeichen ausgegeben werden können:
1
uint8_t udc;
2
for (udc=0;udc<8;udc++) {
3
  lcd_print(1,udc,"%c",udc);  // Die 8 benutzerdefinierten Zeichen
4
}                             // in Zeile 2 des Displays anzeigen

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.