Pseudo-Graphische LCD-Ansteuerung

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

Bei einem HD44780 kompatiblen LCD kann man, in sehr begrenztem Rahmen, auch eigene Zeichen entwerfen und anzeigen.

Das Display verfügt über einen kleinen RAM-Speicher, den sog. Character Generator RAM (CG RAM), in dem 8 selbst definierte 5x8 Pixel große Zeichen Platz finden, oder 4 selbst definierte Zeichen in der Größe von 5x10 Pixeln.

Aus diesem Zeichenvorrat kann man sich bei der Anzeige zusätzlich zu den im Display fest vordefinierten Zeichen bedienen. Der CG RAM kann auch zur Programmlaufzeit beliebig häufig verändert werden. Zu einem Zeitpunkt können aber immer nur maximal 8 (bzw. 4) unterschiedliche selbst definierte Zeichen auf dem gesamten Display angezeigt werden.

Um der Verwirrung vorzubeugen: Häufig wird die Größe der Zeichen mit 5x7 Pixeln angegeben, und nicht 5x8. (Im HD44780-Datenblatt von Hitachi ist immer von 5x8 Pixeln die Rede.) Tatsächlich werden für die meisten Zeichen wirklich nur 5x7 Pixel verwendet, um die unterste Zeile für den Cursor benutzen zu können. Im CG RAM kann man aber alle 8 Zeilen für ein selbst definiertes Zeichen nutzen.

Displays mit Zeichen in der Größe von 5x8 Pixeln

Mit speziellen Kommandos wird der CG RAM beschrieben. Um ein Zeichen zu definieren, muss ein aus 8 Byte bestehendes Bitmuster übertragen werden. Jedes Byte des Bitmusters stellt eine Zeile des Zeichens dar, wobei nur die unteren 5 Bit jeder Zeile relevant sind.

    uint8_t chrdata0[8] = {
        0b00000000,
        0b00000000,
        0b00001010,     //   X X
        0b00011111,     //  XXXXX
        0b00001110,     //   XXX
        0b00000100,     //    X
        0b00000000,
        0b00000000
        };

Die selbst definierten Zeichen haben die Character Codes 0 bis 7. Zu Gunsten der besseren Lesbarkeit werden sie hier als LCD_GC_CHAR0 bis LCD_GC_CHAR7 definiert.

// Set CG RAM Address --------- 0b01xxxxxx  (Character Generator RAM)
#define LCD_SET_CGADR           0x40

#define LCD_GC_CHAR0            0
#define LCD_GC_CHAR1            1
#define LCD_GC_CHAR2            2
#define LCD_GC_CHAR3            3
#define LCD_GC_CHAR4            4
#define LCD_GC_CHAR5            5
#define LCD_GC_CHAR6            6
#define LCD_GC_CHAR7            7

Die Übertragung eines Zeichens erfolgt mit der Funktion lcd_generatechar().

Vorsicht: Nach Übertragung eines benutzerdefinierten Zeichens, muss im LCD-IC explizit eine neue Schreibposition mittels zb lcd_setcursor, lcd_home oder lcd_clear gesetzt werden.

////////////////////////////////////////////////////////////////////////////////
// Schreibt ein Zeichen in den Character Generator RAM

void lcd_generatechar(uint8_t code, const uint8_t *data)
{
    // Startposition des Zeichens einstellen
    lcd_command(LCD_SET_CGADR|(code<<3));

    // Bitmuster übertragen
    for (uint8_t i=0; i<8; i++)
    {
        lcd_data(data[i]);
    }
}

Um eines der selbst definierten Zeichen auf dem Display anzuzeigen, verwendet man wie gehabt die Funktion lcd_data() mit Übergabe des entsprechenden Character Codes.

int main(void)
{
    lcd_init();
 
    uint8_t chrdata0[8] = {
        0b00000000,
        0b00000000,
        0b00001010,     //   X X
        0b00011111,     //  XXXXX
        0b00001110,     //   XXX
        0b00000100,     //    X
        0b00000000,
        0b00000000
        };
    lcd_generatechar(LCD_GC_CHAR0, chrdata0);

    lcd_setcursor(15,1);
    lcd_data(LCD_GC_CHAR0);

    while(1)
    {
    }
 
    return 0;
}

Displays mit Zeichen in der Größe von 5x10(11) Pixeln

Bei den Pixel-Angaben der Displays gibt es mitunter etwas Verwirrung, was nicht zuletzt daran liegt, dass Hitachi in seinem HD44780-Datenblatt keine einheitliche Vorgabe macht. So haben die mit 5x8 Pixeln bezeichneten Displays genau 5x8 Pixel pro Zeichen einschließlich Cursor, während die Bezeichnung mit 5x10 Pixeln den Cursor nicht mit einschließt.

Die 5x10-Displays haben also in Wirklichkeit 5x11 Pixel pro Zeichen. Auch im CG RAM kann man alle 11 Zeilen für ein selbst definiertes Zeichen nutzen.

Um die Schnittstelle variabel zu gestalten, wird die Funktion lcd_generatechar() etwas erweitert:

////////////////////////////////////////////////////////////////////////////////
// Schreibt ein Zeichen in den Character Generator RAM

void lcd_generatechar(uint8_t code, const uint8_t *data, uint8_t lines)
{
    // Startposition des Zeichens einstellen
    lcd_command(LCD_SET_CGADR|(code<<3));

    // Bitmuster übertragen
    for (uint8_t i=0; i<lines; i++)
    {
        lcd_data(data[i]);
    }
}

Bei Displays mit Zeichen in der Größe von 5x10(11) Pixeln können nur 4 selbst definierte Zeichen im CG RAM abgelegt werden, und zwar die Zeichen mit den geraden Character Codes, also LCD_GC_CHAR0, LCD_GC_CHAR2, LCD_GC_CHAR4 und LCD_GC_CHAR6.

int main(void)
{
    lcd_init();
 
    uint8_t chrdata0[11] = {
        0b00000000,
        0b00001010,     //   X X
        0b00011111,     //  XXXXX
        0b00001110,     //   XXX
        0b00000100,     //    X
        0b00000000,
        0b00001010,     //   X X
        0b00011111,     //  XXXXX
        0b00001110,     //   XXX
        0b00000100,     //    X
        0b00000000
        };
    lcd_generatechar(LCD_GC_CHAR0, chrdata0, 11);

    lcd_setcursor(15,1);
    lcd_data(LCD_GC_CHAR0);

    while(1)
    {
    }
 
    return 0;
}