Prinzipiell sollte ein HD44780 kompatibles Display (oder auch KS0070) verwendet werden. Als Quelle können beispielsweise die alphanumerischen Displays von Conrad Electronic bzw. Reichelt dienen. Ich habe beispielsweise ein 2x16 Display verwendet. Dieses erscheint mir für den Anfang vollkommen ausreichend.
Auf die Verwendung von Grafik-LCDs werde ich nicht eingehen, da mir deren Verwendung im Rahmen meiner Projekte als nicht sinnvoll erscheint. Außerdem ist deren Ansteuerung wesentlich komplexer.
Die Pinbelegung des LC-Displays lässt sich aus dem Datenblatt wie folgt entnehmen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
VSS
VDD
VO
RS
R/W
E
DB1
DB2
DB3
DB4
DB5
DB6
DB7
DB8
BLA
BLK

 Hierbei ist VSS Masse, VDD die Betriebsspannung von +5V und VO die Kontrastspannung. Pin 4 bis 6 dienen der Steuerung des Displays. Auf Pin 7 bis 14 erfolgt die Übertragung der Datenbits, 15 und 16 dienen dem Anschluss einer Hintergrundbeleuchtung, falls das Display über eine verfügt.
Eine Anschlussvariante eines solchen Displays stellt die folgende Grafik dar:

 Prinzipiell kann man ein solches Display entweder im 8-Bit-Modus oder im 4-Bit-Modus ansteuern. Da der ATmega8 nicht gerade über sehr viele IO-Pins verfügt, habe ich mich für den 4-Bit-Modus entschieden. So spart man 4 Pins am Controller ein, welche man anderweitig verwenden kann.
Der einzige Nachteil ist, dass man nun zum Übertragen eines einzigen Bytes zwei Schreibzugriffe durchführen muss in nicht wie im 8-Bit-Modus nur einen. Es wird zuerst das höhere Nibble (Bit 7...4) und danach das niedere Nibble (Bit 3...0) übertragen.
Nach dem Aufbau der obigen Schaltung sollte beim Zuschalten der Betriebsspannung mindestens ein schwarzer Balken zu sehen sein. Das Display kann natürlich auch an einen anderen Port des MC angeschlossen werden, hierbei müssten aber in der Bibliothek die entsprechenden Pins abgeändert werden.

Möchte man das Display vom MC aus ansteuern, so muss dieses zuerst ordnungsgemäß initialisiert werden. Wie das funktioniert, kann man im Normalfall dem Datenblatt entnehmen.
Zuerst muss man den entsprechenden Port, im Beispiel PORTD als Ausgang definieren. Dies könnte zum Beispiel so aussehen:
DDRD = 0xFF;
Da nach dem Einschalten des Displays mindestens 15ms gewartet werden soll, wird nun ein entsprechendes Delay eingefügt.
delay(20000);
Im nächsten Schritt sollen DB4 und DB5 am Display auf High-Pegel gesetzt werden.
PORTD = 0x30>>4;                                            //entspricht 0b00110000
Um dem LCD mitzuteilen, dass es diesen Wert übernehmen kann, muss kurz dessen E-Port (Nr. 6) auf high und danach gleich wieder auf low gesetzt werden. Dies erfolgt durch folgende Kommandos:
PORTD |= (1<<PD6);
__asm__ __volatile__( "rjmp 1f\n 1:" );            
//warte 500ns
PORTD &= ~(1<<PD6);

Am praktischsten ist es, diese Befehle in eine eigenständige Funktion zu schreiben, da man sie häufiger benötigt (Bsp. toggle_e ( )).
Nun muss laut Datenblatt länger als 4,1ms gewartet werden, bis der Displaycontroller die Daten übernommen hat. Danach muss noch einmal das selbe Bitmuster an den PORTD ausgegeben werden. Nun muss erneut mindestens 100μs gewartet werden.
Da es soviel Spaß gemacht hat, muss sich dieser ganze Zyklus nun auch noch ein drittes Mal wiederholen.
Nun ist das Display soweit, dass man ihm sagen kann, in welchem Funktionsmodus man es betreiben möchten. In diesem Fall ist es der 4-Bit-Modus, das Display hat zwei Zeilen und ein einzelner Charakter hat 5*7 Pixel.
Begonnen wird mit der Initialisierung des 4-Bit-Modus.
PORTD = 0x20>>4;                                             //entspricht 0b00100000
toggle_e();
delay(100);

Hiermit wird eine logische '1' an DB5 gelegt, wie es laut Datenblatt auch erforderlich ist, um die Funktionsweise zu definieren. Da DB4 auf '0' liegt, erkennt der Displaycontroller, dass der 4-Bit-Modus verwendet werden soll.
Als nächstes soll dem Display begreiflich gemacht werden, das beide Zeilen genutzt werden. Hierzu muss laut Datenblatt eine 0x28 an den Datenpins des Displays anliegen, da aber nur vier der Pins genutzt werden, kann die Einstellung des Modus nicht einfach durch PORTD=0x28 erfolgen (DB3 und DB5 müssen auf H-Pegel gesetzt werden).
Hierzu wird zuerst durch das Lesen des Busy-Flags geprüft, ob das Display bereit ist. Ist es gelöscht, so können die Daten geschrieben werden. Ist es bereit, so muss ihm klar gemacht werden, dass die folgenden Daten als Befehl zu deuten sind. Dies erfolgt durch RS=0 (PD4 am AVR) und RW=0 (liegt soundso auf Masse). Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst.
PORTD = (data>>4)&0x0F;
toggle_e();
PORTD = data&0x0F;
toggle_e();

In diesem Fall ist data = 0x28, wie es bereits oben erwähnt wurde.
Dann werden alle Datenpins wieder auf logisch '0' gesetzt.
PORTD = 0x0F;
Laut Datenblatt muss man, um das Busy-Flag zu lesen RW auf High-Pegel und RS auf Low-Pegel setzen, d.h. für die Pins am AVR, dass PD5 auf '1' und PD4 auf '0' gesetzt werden müssen.
Zur Überprüfung des Busy-Flags muss zunächst der entsprechende Pin am Controller (PD7) als Eingang konfiguriert werden. Dann kann man Prüfen, ob eine logische '1' anliegt oder ob der Pin auf logisch '0' liegt.
PORTD |= (1<<PD5);              //RW=1 Lese-Modus
DDRD = 0xF0;                        
//als Eingang definieren

Liegt DB7 am Controller auf '1', so bedeutet das, dass er gerade beschäftigt ist, andernfalls ist er bereit.
Vor dem Lesen muss an Pin 6 am Controller (E - - > chip enable) eine '1' liegen, nach dem Lesezugriff kann dieses Bit wieder gelöscht werden.
PORTD |= _BV(PD6);
__asm__ __volatile__( "rjmp 1f\n 1:" );        
//delay (500ns)
dataH = PIND;                                               
//zuerst hohes Nibble lesen
PORTD &= ~(1<<PD6);
__asm__ __volatile__( "rjmp 1f\n 1:" );        
//delay
PORTD |= (1<<PD6);
__asm__ __volatile__( "rjmp 1f\n 1:" );        
//delay
dataL = PIND;                                                
//lese niederes Nibble
PORTD &= ~(1<<PD6);

Dieser Code liest neben dem Busy-Flag gleich noch den Adresszähler aus. Die Überprüfung, ob Bit 7 auf logisch '1' ist (entspricht DB7)sollte nun auch keine Hürde mehr sein.

Nun funktioniert das Display also im 2-Zeilen-Betrieb.
Als nächstes soll das Display ausgeschaltet werden. Dies erfolgt durch das Senden von 0x08 (vgl. Datenblatt). Das Senden erfolgt analog zu der obigen Erklärung (dort war es 0x28 für den 4-Bit-Modus).
Danach muss das Display gelöscht werden. Hierzu muss 0x01 gesendet werden (vgl. Datenblatt).
Zu guter letzt muss noch der Start-Modus (entry mode) definiert werden. Hier soll das Display einfach aktiviert und der Cursor deaktiviert werden. Dies erfolgt durch Senden von 0x0C.

Hiermit ist die Initialisierung des Displays abgeschlossen!

Prinzipiell empfehle ich den Download der LCD-Library von Peter Pfleurys Homepage (siehe Rubrik Links), da sie universell einsetzbar für alle HD44780 kompatiblen alphanumerischen Displays ist. Sie ist über ein Header-File leicht modifizierbar.

Das Schreiben von Daten auf dem Display funktioniert mit den bereits oben angeführten Befehlen. RS muss auf H-Pegel sein, R/W auf Low. Nun können die Daten wie oben beschrieben Nibble für Nibble an das Display übertragen werden. Für die genaue Funktionsweise und Reihenfolge der Prozeduren sei auf die in der Bibliothek enthaltenen Funktionen verwiesen. Diese sollten mit obigen Erklärung relativ leicht zu verstehen sein.

 

Zurück zur Startseite.