Zurück zum Menü 12
12.1.6 LCD-Display am Mikrocontroller

Erstellt ab  04.01.2012 
-----  © Reinhard N.

Dot-Matrix-LCD-Displays eignen sich aufgrund ihres erträglichen Preises und des geringen Ansteueraufwands gut als Ausgabemedium eines Mikrocontrollers. Wenn der Controllerchip HD44780 (oder kompatibel) eingebaut ist, benötigt man zur Ansteuerung acht Daten- und drei Steuerleitungen sowie die Stromversorgung , Kontrastanschluss und evtl. zwei Leitungen zur Hintergrundbeleuchtung. Eine klar verständliche Beschreibung findet man unter http://www.sprut.de/electronic/lcd/index.htm

Da die Ausgangsleitungen eines Mikrocontrollers wertvoll sein können, kann man es sich nicht immer leisten, 9 Leitungen für eine Anzeige zu belegen. Selbst die Reduzierung auf eine 4-Bit-Datenübertragung und Verzicht auf die Möglichkeit, aus dem Display zu lesen, erfordert immer noch sechs Anschlüsse: 4 Daten und 2 Steuerleitungen.

Die Idee, ein Interface mittels Schieberegister zu bauen, lag schon lange in der Luft, die Realisierung ließ aber auf sich warten, da die Steuerleitungen irgendwie (gedanklich) nicht untergebracht werden konnten. Die Lösung lieferte ein Beitrag in der Zeitschrift Elektor (5/2008, Seite 26). Die Steuersignale RS und E werden mit ins Schieberegister gegeben und dann wird der Übernahmeimpuls (Steuerleitung E) mittels UND-Schaltung aus dem entsprechenden Registerausgang und Daten-Signal erzeugt. Da die veröffentlichte Schaltung hierzu eine Diode heranzog, das aber nicht auf Anhieb funktionierte, wurde ein ganz normales UND-Gatter (7408) benutzt. Das mag vielleicht aufwändiger erscheinen, ist aber nicht teurer; außerdem funktionierte die Schaltung auf Anhieb sowohl mit PIC16F628 (5 V) als auch mit MSP430G2231 (3,3 V). Der Gewinn: es werden nur zwei Anschlüsse des Mikrocontroller belegt: eine als Datenleitung, die andere als Takt.

 Als Schieberegister kommt das IC 4094 ( 8-Bit-Schieberegister) zum Einsatz. Man könnte aber auch das IC 4015 (2 x 4-Bit-Schieberegister) nehmen, welches ebenfalls erfolgreich getestet wurde. Zur Kontrasteinstellung kann man ein Potentiometer in der Größenordnung    5 kOhm bis etwa 20 kOhm nehmen (R1 im Schaltplan). Möchte man eine Hintergrundbeleuchtung benutzen, empfiehlt es sich, einen Vorwiderstand zu benutzen. Die Größe hängt vom jeweiligen Display ab, evtl. zwischen 15 und 80 Ohm. Teils ist dieser Widerstand schon in dem Anzeige-Element eingebaut. Das sollte man testen. Im Schaltplan ist ein Jumper vorgesehen, so dass man einerseits ohne und andererseits mit Widerstand  (R2) arbeiten kann.


Der Schaltplan sieht so aus:



Natürlich erfordert diese Lösung ein eigenes Programm zur Ansteuerung. Das ist aber nicht wirklich aufwändig:

1. Schieberegister löschen (Daten Low, 8 Takte High/Low)
2. Zu übertragendes Datenwort in zwei Nibble aufteilen
3. Oberes Nibble im zu übertragenen Datenwort positionieren
4. Steuerbefehle hinzuaddieren
5. Acht bit des Datenwortes übertragen
6. Schieberegister löschen (Daten Low, 8 Takte High/Low)
7. Unteres Nibble im zu übertragenen Datenwort positionieren
8. Steuerbefehle hinzuaddieren
9. Acht bit des Datenwortes übertragen

Damit ist ein Zeichen gesendet.



Dieses Verfahren könnte als C-Programm so aussehen:
(Eine Übertragung nach BASIC dürfte nicht schwer sein. Hinweise sind auch im genannten Elektor-Artikel zu finden.)


Die Funktionen delay_ms()  und  delay_us() sind selbst zu schreibende Verzögerungsroutinen  im Milli- und Mikrosekundenbereich

#define High_Takt() {delay_us(1); PORTQ|=Takt;  }    PortQ ist der entspr. µC-Ausgang
#define Low_Takt()  {delay_us(1); PORTQ&=~Takt; }
#define High_Daten(){delay_us(1); PORTQ|=Daten; }
#define Low_Daten() {delay_us(1); PORTQ&=~Daten;}

//*****************************************
// Zeichen ans Display senden
//*****************************************           
void Text_zchn_senden( unsigned char zchn) {
    unsigned char zh;
    unsigned char zl;
    zh = zchn & 0xF0;            // High-Nibble
    zl = zchn & 0x0F;            // Low-Nibble
    zh = zh>>3;                // Positionierung
    zh = zh + 64 + 32;                  // Steuerzeichen dazu
    datentransfer(zh);            // High-Nibble senden
    zl = zl <<1;                // Positionierung
    zl = zl + 64 + 32;             // Steuerzeichen dazu
    datentransfer(zl);             // Low-Nibble senden
}

//*****************************************
// Commando ans Display senden
//*****************************************   
void Steuer_zchn_senden(unsigned char zchn) {
    unsigned char zh;
    unsigned char zl;
    zh = zchn & 0xF0;            // wie Zeichen senden,
    zl = zchn & 0x0F;            // nur hier RS = 0    (Bit5)
    zh = zh>>3;
    zh = zh + 64 ;
    datentransfer(zh);
    zl = zl <<1;
    zl = zl + 64 ;
    datentransfer(zl);
}

//*****************************************
// tatsächliche Übertragung des Zeichens
//*****************************************
void datentransfer(unsigned char data) {
    int i;                        // in das Schieberegister schreiben
    Low_Daten();
    for(i=0; i<8; i++) {
        High_Takt();
        Low_Takt(); }
    for(i=0; i<8; i++) {
        if(data & 0x80) {High_Daten();}
        else {Low_Daten();}
        High_Takt();
        Low_Takt();
        Low_Daten();
        data=data<<1;}
                                // jetzt E setzen
        High_Daten();
        Low_Daten();
}

Natürlich muss das Display initialisiert werden. Das geschieht über:

//*********************************************
//Stellt die Funktionsweise der LCD Anzeige ein
//*********************************************   
void init_lcd(void){
    unsigned int i;
    unsigned char zchn;
    delay_ms(500);
    for(i=1; i<4; i++) {
        zchn = 3*2 + 64;
        datentransfer(zchn);
        delay_ms(50);}
    zchn = 2*2 + 64;   
    datentransfer(zchn);
    delay_ms(50);
    Steuer_zchn_senden(0x28);
    delay_ms(1);
    Steuer_zchn_senden(0x01);
    delay_ms(1);
    Steuer_zchn_senden(0x06);
    delay_ms(1);
    Steuer_zchn_senden(0x0c);
    Steuer_zchn_senden(0x01);    // CLEAR_DISPLAY
}
//*****************************************






Liebe Grüße,

Reinhard





Nach oben            Zurück zum Menü 12