LCD Display mit I2C Ansteuermodul (HW-061)
| LCD PIN | Pin am I2C Modul HW-061 |
|---|---|
| VSS (Voltage Source) | GND |
| VDD (Voltage Drain) | +5 V |
| VO (Contrast Control) | analoge Spannung zwischen 0-5 V |
| RS (Register Select) | Port 0 (0=GND, 1=VCC) |
| RW (Read/Write) | Port 1 (0=GND, 1=VCC) |
| EN (Enable) | Port 2 (0=GND, 1=VCC) |
| D0 - D3 | dauerhaft +5V |
| D4 - D7 | Port 4 - Port 7 (0=GND, 1=VCC) |
| A | dauerhaft +5 V |
| K | Port 3 auf GND (0=VCC, 1=GND,) |
Das Modul HW-061 dient zum einfachen ansteuern eines standard LCD Displays mit 16 Anschlusspins. Statt den 16 Anschlussleitungen werden aufgrund der I2C Übertragung nur 4 Leitungen benötigt (VCC, GND, SDA, CLK). Mit dem eingebauten Poti kann man den Kontrast einstellen und mit dem Jumper die Hintergrundbeleuchtung an- und ausschalten. Kern des HW-061 Moduls ist ein 8-bit Port-Expander IC (PCF8574) welcher die I2C Signale in 8 parallel anliegende Ausgangspegel umwandelt. Das LCD Display selbst und die Ansteuerung eines I2C Port-Expanders sind bereits in vorhergegangenen Kapitel vorgestellt worden.
Hier eine Tabelle mit einer Übersicht welcher Ausgang des HW-061 welchem Eingang des LCD Displays entspricht. Die Ports P0-P7 werden über I2C Daten gesteuert.
I2C Port-Expander (PCF8574)
Der PCF8574 antwortet nicht auf die allgemeine I2C "Call Address". Die voreingestellte Adresse ist 0x27. Falls man eine andere Adresse benötigt kann diese über 3 Lötbrücken verändert werden. Nachfolgend nochmal eine Übersicht welches bit welchem LCD Eingang entspricht. Die Ports P4-P7 dienen zum Übertragen von Daten und die Ports P0-P4 zum schalten der Steuerleitungen. Die Pinbezeichnungen und die nachfolgenden Befehle sind im Kapitel LCD Display ausführlich erklärt.
| P7 | P6 | P5 | P4 | P3 | P2 | P1 | P0 |
| D7 | D6 | D5 | D4 | LED | EN | RW | RS |
Programmcode ohne die Verwendung einer Bibliothek
Die Befehle für das IR oder die Anzeigedaten für das DR liegen immer als 8 bit vor (außer der erste Befehl zum
Einstellen des 4-Bit-Modus). Im 4-Bit-Modus mussen die 8 bit daher auf 2x gesendet werden (P4-P7). In der
datenSenden() Funktion werden die 8 Daten bit daher zunächst aufgeteilt und an die Stellen P4-P7
verschoben. An die Stellen P0-P3 werden Werte für die Steuerleitungen kopiert. LED=1 (Hintergrundbeleuchtung an),
RW=0 (Schreibmodus), RS= 1/0 (abhängig ob in das Befehlsregister geschrieben werden soll RS=0, oder in das
Datenregister RS=1).
Der EN Pin von den Steuerleitungen an P2 muss einmal seinen Pegel von 1 auf 0 ändern. Erst bei diesem Flankenwechsel werden die anliegenden Pegel von den vom LCD Display übernommen. Das ist auch der Grund, warum jedes Halbbyte 3x übertragen wird.
#include "Wire.h" // Anschluss-Pins I2C: SDA=A4, CLK=A5
#define IR 0 // Instruction Register
#define DR 1 // Data Register
void setup() {
Wire.begin();
datenSenden(IR, B00000010); // 4-Bit Übertragungsmodus
datenSenden(IR, B00101000); // Function Set
datenSenden(IR, B00001110); // Display Control
datenSenden(IR, B00000001); // Clear Display
}
void loop() {
datenSenden(DR, 'H');
datenSenden(DR, 'a');
datenSenden(DR, 'l');
datenSenden(DR, 'l');
datenSenden(DR, 'o');
while(true);
}
Funktion datenSenden()
#define adresse 0x27
void datenSenden(bool rs, byte daten) {
//daten aufteilen in zwei Halbbytes
byte oberesHalbByte = daten & B11110000;
byte unteresHalbByte = (daten & B00001111) << 4;
//Steuerleitungen dazu schalten X|X|X|X|LED=1|EN=1|RW=0|RS=1
byte erstesSendeByte = oberesHalbByte | B00001101;
byte zweitesSendeByte = unteresHalbByte | B00001101;
// wenn ins Instruction Register geschrieben werden soll: RS=0
if (rs == 0) {
erstesSendeByte &= B11111110;
zweitesSendeByte &= B11111110;
}
// Daten auf I2C übertragen 3x erstesSendeByte und 3x zweitesSendebyte
// ... jeweils mit einem Enable (EN=0) Puls dazwischen
Wire.beginTransmission(adresse);
Wire.write(erstesSendeByte);
Wire.endTransmission();
Wire.beginTransmission(adresse);
Wire.write(erstesSendeByte & B11111011); // EN = LOW
Wire.endTransmission();
Wire.beginTransmission(adresse);
Wire.write(erstesSendeByte);
Wire.endTransmission();
delayMicroseconds(100);
Wire.beginTransmission(adresse);
Wire.write(zweitesSendeByte);
Wire.endTransmission();
Wire.beginTransmission(adresse);
Wire.write(zweitesSendeByte & B11111011); // EN = LOW
Wire.endTransmission();
Wire.beginTransmission(adresse);
Wire.write(zweitesSendeByte);
Wire.endTransmission();
delay(20);
}
Programmcode mit der Bibliothek LiquidCrystal_I2C.h
LiquidCrystal_I2C myLCD (I2C Adresse, Anzahl Stellen, Anzahl Zeilen)
Erstellt eine Instanz von von LiquidCrystal_I2C und übernimmt die Modul-Adresse und die Displaymaße.
myLCD.init()
Initialisiert das Display mit den Grundeinstellungen
myLCD.backlight() und myLCD.noBacklight()
Schaltetet die Hintergrundbeleuchtung an oder aus. Die Displayanzeige wird dadurch nicht gelöscht.
myLCD.clear()
Löscht das Display und setzt den Cursor links in die erste Reihe.
myLCD.home()
Setzt den Cursor ganz links in die ersten Reihe. Ohne den Displayinhalt zu löschen.
myLCD.setCursor(Stelle, Zeile)
Setzt den Cursor an die entsprechende Stelle (0= vorderste Stelle) in der entsprechenden Zeile (0= oberste
Zeile). Je Zeile kann der Cursor an 40 Stellen (0-39) gesetzt werden. Wenn der Displayinhalt mit
scrollDisplayLeft() oder scrollDisplayRight() noch nicht bewegt wurde werden
standardmäßig die ersten 16 Stellen angezeigt.
myLCD.cursor() und myLCD.noCursor()
Mit diesen Befehlen wird der Cursor als Unterstrich an der Stelle an der als nächste geschrieben werden soll angezeigt. Mit noCursor() wird der Unterstrich wieder ausgeblendet.
myLCD.blink() und myLCD.noBlink()
Mit diesem Befehl wird der Cursor als blinkendes Rechteck an der Stelle angezeigt, an der als nächstes geschrieben wird. Mit noBlink() wird das blinkende Rechteck wieder ausgeschalten.
myLCD.display() und myLCD.noDisplay()
Mt diesen Befehlen kann der Displayinhalt aus und wieder eingeschaltet werden. Im ausgeschalteten Zustand bleibt der Inhalt gespeichert. Die Hintergrundbeleuchtung bleibt auch im ausgeschalteten Modus an.
myLCD.scrollDisplayLEFT() und myLCD.scrollDisplayRight()
Durch diese Befehle kann der sichtbare Ausschnitt (die 16 derzeit angezeigten Stellen) nach links oder rechts bewegt werden.
myLCD.autoscroll() und noAutoscroll()
Mit autoscroll()kann auf einer Displaystelle geschrieben werden. Anstatt dass sich der Cursor
weiterbewegt bewegt sich mit diesen Befehlen der ganze Displayinhalt. Mit noAutoscroll() wird wieder
auf die Cursor Bewegung geschalten.
leftToRight() und rightToLeft()
Legt die schreibrichtung fest. Also die Bewegung des Cursors nach dem ein Buchstabe geschrieben wurde.
myLCD.write() und myLCD.print()
Mit diesen Befehlen können einzelne Zeichen (character) oder ganze Strings auf das display übertragen werden.
#include "LiquidCrystal_I2C.h"
LiquidCrystal_I2C myLCD(0x27,16,2); // Slave Adresse, Zeichen pro Zeile, Anzahl Zeilen
void setup() {
myLCD.init();
myLCD.backlight();
}
void loop() {
myLCD.print("Hallo!!!"); delay(1000);
myLCD.noBacklight(); delay(1000);
myLCD.backlight(); delay(1000);
myLCD.setCursor(0,1);
myLCD.print("alles wird gut!"); delay(1000);
myLCD.clear(); delay(1000);
}