LCD1602

In der Praxis kann es passieren, dass Informationen an den Anwender herangetragen werden müssen, die mit einer blinkenden LED nicht mehr dargestellt werden können. Für diese Fälle bietet es sich an eine LCD-Anzeige zu benutzen. Mit ihr ist es möglich, zwei Zeilen mit je 16 Zeichen anzuzeigen. Die Anzeige benötigen mindestens 6 Anschlüsse. Davon sind 4 Anschlüsse nur für Daten, während die anderen beiden Anschlüsse für die Steuerung des LCD1602 benutzt werden. Es gibt auch einen 8-Bit-Modus, bei dem 4 Anschlüsse mehr benötigt werden. Für diesen Modus bietet sich die Verwendung des 74HC595N an. In diesem Tutorial wird der 4-Bit-Modus verwendet. Es wird gezeigt, wie man die Anzeige initialisiert und dann zeilenweise beschreibt. Als Beispiel werde ich Eingaben in die Konsole auf dem Display anzeigen lassen.

Inhalt


Material

  • LCD1602
  • 3000 Ohm Widerstand
  • Diverse Kabel
  • Steckbrett

Aufbau

Der LCD1602 hat viele Anschlüsse, von denen nur 6 mit dem Raspberry Pi verbunden werden müssen. Das Modul sieht so aus:

LCD1602
Mit A und K schaltet man die LED Hintergrundbeleuchtung ein. Anschluss A schließt man an +3V3 und K an GND an. VDD muss an +5V angeschlossen werden, während man VSS an GND anschließt. Mit V0 stellt man den Kontrast des Displays ein. Dieser muss an GND angeschlossen werden. Ich habe den besten Kontrast, wenn ich einen 3000 Ohm Widerstand zwischen schalte. Mit RW stellt man ein, ob man den LCD Speicher beschreiben oder auslesen will. In unserem Fall wollen wir ihn nur beschreiben. Dazu muss RW an GND angeschlossen werden. Der Anschluss RS muss mit dem Raspberry Pi verbunden werden. Mit dem stellt man ein, ob in den Daten ein Kommando zur Steuerung des Displays oder ein Symbol für die Anzeige auf dem Display ist. Ein Peak an E führt dazu, dass das Display die Daten übernimmt. Die Daten befinden sich in D4:D7. Im 4-Bit-Modus bleiben D0:D3 frei.

Daraus ergibt sich folgender Gesamtaufbau:

Gesamtaufbau
Statt dem 3000 Ohm Widerstand kann man auch einen Potentiometer einbauen und den optimalen Widerstand einstellen. Ansonsten besteht nun die Aufgabe darin Daten anzulegen, den Modus auf Kommando oder Symbol zu setzen und dann ein Peak an E anlegen.

Programm

Auch hier geht es wieder als erstes damit los die Anschlüsse zu initialisieren:
#define PINRS 24
#define PINE 25
#define PINDATA4 29
#define PINDATA5 28
#define PINDATA6 27
#define PINDATA7 26

void init() {
    pinMode(PINE, OUTPUT);
    pinMode(PINRS, OUTPUT);
    pinMode(PINDATA4, OUTPUT);
    pinMode(PINDATA5, OUTPUT);
    pinMode(PINDATA6, OUTPUT);
    pinMode(PINDATA7, OUTPUT);

    digitalWrite(PINE, LOW);
    digitalWrite(PINRS, LOW);
    digitalWrite(PINDATA4, LOW);
    digitalWrite(PINDATA5, LOW);
    digitalWrite(PINDATA6, LOW);
    digitalWrite(PINDATA7, LOW);
}
Als nächstes folgen die Funktionen, die dazu nötig sind ein einzelnes Zeichen zu schreiben. Zuerst die Funktion für den Peak an E:
#define DELAYCONST 100

void E_Tick() {
    digitalWrite(PINE, HIGH);
    delayMicroseconds(DELAYCONST);
    digitalWrite(PINE, LOW);
    delayMicroseconds(DELAYCONST);
}
Es werden von einem Byte nur 4 Bits gleichzeitig in die Pins geschrieben. Dazu habe ich eine Funktion erstellt, die immer die höchsten 4 Bits eines Bytes in die Ausgänge schreibt:
void resetDataOutput() {
    digitalWrite(PINDATA4, LOW);
    digitalWrite(PINDATA5, LOW);
    digitalWrite(PINDATA6, LOW);
    digitalWrite(PINDATA7, LOW);
}

void writeNibble(char n) {
    resetDataOutput();

    if((n&0x10) == 0x10) {
        digitalWrite(PINDATA4, HIGH);
    }
    if((n&0x20) == 0x20) {
        digitalWrite(PINDATA5, HIGH);
    }
    if((n&0x40) == 0x40) {
        digitalWrite(PINDATA6, HIGH);
    }
    if((n&0x80) == 0x80) {
        digitalWrite(PINDATA7, HIGH);
    }

    E_Tick();
}
Es werden erst die Ausgänge auf 0 gesetzt. Anschließend werden die höchsten 4 Bits überprüft, ob sie auf 1 gesetzt sind und dann entsprechend die Ausgänge geändert. Zum Schluss wird ein Peak an E angelegt.

Damit ist es ganz leicht ein Byte an das Display zu senden:
void writeByte(char b, char mode) {
    digitalWrite(PINRS, mode);
    writeNibble(b);
    writeNibble(b<<4);
}
Die Übergabevariable 'mode' bestimmt dabei, ob es sich um ein Kommando zum Steuern des Displays oder um ein Symbol für die Anzeige handelt.

Bevor Daten auf dem Display angezeigt werden können, muss dieses initialisiert werden. Dazu halte ich mich streng an das Datenblatt:
#define LCD_CMD LOW

void display_init() {
    writeByte(0x33, LCD_CMD); // 0b00110011
    writeByte(0x32, LCD_CMD); // 0b00110010
    writeByte(0x28, LCD_CMD); // 0b00101000
    writeByte(0x0C, LCD_CMD); // 0b00001100
    writeByte(0x01, LCD_CMD); // 0b00000001
    writeByte(0x06, LCD_CMD); // 0b00000110
}
Für einen normalen Betrieb im 4-Bit-Modus können diese Kommandos einfach kopiert werden. Wichtig ist, dass sie in genau dieser Reihenfolge aufgerufen werden.

Anschließend muss eine Funktion geschrieben werden, die eine ganze Zeile auf das Display schreibt:
#define LCD_LENGTH 16
#define LCD_CHR HIGH

void writeLine(std::string msg) {
    for(int i = 0; i < msg.length(); i++) {
        if(i < LCD_LENGTH) {
            writeByte(msg[i], LCD_CHR);
        }
    }
}
Anschließend folgen einige Hilfsfunktionen, die für die Arbeit mit dem Display erforderlich sind. Als erstes kommen Funktionen zur Wahl der Zeile:
#define LCD_LINE1 0x80
#define LCD_LINE2 0xC0

void jumpToLine(char l) {
    writeByte(l, LCD_CMD);
}

void jumpToFirstLine() {
    jumpToLine(LCD_LINE1);
}

void jumpToSecondLine() {
    jumpToLine(LCD_LINE2);
}
Die Konstanten für LCD_LINE1 und LCD_LINE2 kommen ebenfalls aus dem Datenblatt.

Es folgen Funktionen zum Löschen einer Zeile:
void clearLine(char l) {
    jumpToLine(l);
    writeLine(std::string(LCD_LENGTH,' '));
}

void clearFirstLine() {
    clearLine(LCD_LINE1);
}

void clearSecondLine() {
    clearLine(LCD_LINE2);
}
Dies kommt dann in Hilfsfunktionen zum zeilenweise schreiben auf das Display zusammen:
void writeToFirstLine(std::string msg) {
    clearFirstLine();
    jumpToFirstLine();
    writeLine(msg);
}

void writeToSecondLine(std::string msg) {
    clearSecondLine();
    jumpToSecondLine();
    writeLine(msg);
}
Das Löschen einer Zeile ist wichtig, da sonst kurze Zeilen eine ältere längere Zeile nicht komplett überschreiben würden. Anschließend muss in die entsprechende Zeile, in die geschrieben werden soll, gesprungen werden. Dann kann mit der writeLine() Funktion der entsprechende Text geschrieben werden.

Genutzt wird nun alles in einer main-Funktion, in der Zeile für Zeile Konsoleneingaben eingelesen und auf dem Display angezeigt werden.
int main() {
    if(wiringPiSetup() == -1) {
        return 0;
    }

    init();
 
    display_init();

    std::string s;

    while(1) {
        std::getline(std::cin, s);
        writeToFirstLine(s);
        std::getline(std::cin, s);
        writeToSecondLine(s);
    }
 
    return 0;
}
Ich hoffe dieses Tutorial hat euch bei der Verwendung des LCD1602 weitergeholfen oder euch seinen Nutzen näher gebracht und euch zum Kauf angeregt. Für weitere Informationen zum LCD1602 siehe:

Keine Kommentare:

Kommentar veröffentlichen

Hinweis: Nur ein Mitglied dieses Blogs kann Kommentare posten.