Arduino NANO:    LCD-Display EAT123A
 

 
Schaltungsdiagramm für das LCD-Display EAT123A am I2C-Bus des NANO-Boards
 
Das dem EAT123A beigefügte Datenblatt ist ein miserabler Zusammenschnitt des Datenblattes für dessen Treiberbaustein PCF 2116. Hier das Datenblatt der Bausteine PCF 2114 und PCF 2116.
Datenblatt PCF 2116 .. (EAT123A)
 
Bemerkungen:
1. Die Wire-Bibliothek des Arduino NANO arbeitet mit 7Bit Adressangaben für Slave-Bausteine. So muß die im Datenblatt des EAT123 angegebene Adresse 0x74 um ein Bit nach rechts geschoben werden, wodurch aus ihr die Adresse 0x3A wird.
 
2. Das in der Adresse des EAT123 angegebene Datenbit SA0 bezeichnet einen Pin am Treiberbaustein PCF 2116. Auf dieses Bit wird in der Beschreibung nicht weiter eingegang. Nach der handschriftlichen Adressangabe des Datenblattes muß dieses Bit hardwarmäßig auf 0 gelegt sein.
 
3. Die Angaben zu den Bits RS und R/W der Tabelle 'Instructions' müssen vor der Angabe einer bestimmten Funktion aus dieser Tabelle über ein 'control byte' gesetzt werden. Dieses baut sich wie folgt auf .. C0, RS, R/W, x xxxx .. Hierbei besitzt das Bit C0 folgende Bedeutung ..
                                 C0=0 einziges Control-Byte, es folgen nur noch Daten-Bytes
                                 C0=1 die nächsten zwei Bytes sind ein 1. ein Daten-Byte und 2. ein Control-Byte (s.read DDram)
 
4a G=1: Aus dem beigefügten Datenblatt geht hervor, dass das Display an nur einer Spannung (+5V) arbeitet. Aus dieser Erkenntnis folgt, dass das in der Tabelle 'Instructions' unter 'Function Set' angegebene Bit G auf 1 gesetzt sein muß, damit das Display arbeitet. Bei G=0 fällt es aus.
4b. DL=x: Im I2C-Modus werden grundsätzlich 8 Bit übertragen. Daraus folgt, dass das unter 'Function Set' angegebene Bit DL ohne Bedeutung ist.
 

Ausgabe-Programm für das LCD-Display EAT123A
/*
LCD-Display EAT123A-I2C
=======================
Die Anzeige besitzt 3 Zeilen mit je 12 Zeichen, wobei im DDram pro Zeile 19 Speicher bereitstehen.
Im Programm erfolgte die Initialisierung als Display mit 4 Zeilen (N=1, M=1), wobei die 4.Zeile ungenutzt
bleibt. Beim Aufruf eines der Unterprogramme beginnt die Nummerierung der Zeilen (z) sowie der Spalten
(s) mit 1 (innerhalb der Unterprogramme lautet die Nummerierung 0,1,2 ..
 
*/

#include <Wire.h>                             // Einbinden der Wire-Bibliothek des Arduino NANO
#define I2CadrLCD 0x3A                        // 7 Bit Basisadresse des EAT123A 0x3A = 011 1010
                                              // oder    byte I2CadrLCD = 0x74>>1
 
String TXTstrg1 = "3x12 Zeichen";             // auszugebende Teststrings
String TXTstrg2 = "I2C Bus";
String TXTstrg3 = "2.56mm flach";
 
 
// Ausgabetest
// die Wartezeiten dienen der Übersicht während der Ausgaben
// Dieser Programmteil muß durch eigene Ausgaben ersetzt werden
// ------------------------------------------------------------
void ausgabetest () {
   print_TXT(1,1,TXTstrg1);                   // TextString 1 ausgeben
   print_TXT(2,3,TXTstrg2);                   // TextString 2 ausgeben
   print_TXT(3,1,TXTstrg3);                   // TextString 3 ausgeben
 
   delay (2000);                              // 2 Sekunden warten
   clr_line(3);                               // Zeile 3 löschen
   clr_line(2);                               // Zeile 2 löschen
 
   delay (2000);                              // 2 Sekunden warten
   print_TXT(3,2,"Display");                  // angegebenen Text in Zeile 3 ausgeben
 
   delay (2000);                              // 2 Sekunden warten
   print_TXT(3,9,"OK");                       // zusätzlichen Text in Zeile 3 ausgeben
   delay (2000);                              // 2 Sekunden warten
   cursor_on (0);                             // Cursor ausschalten
   
                                              // -------------------------------------------
                                              // Test, den DDram auslesen
   Serial.begin (9600);                       // .. nur für die Textausgabe bei read_DDram()
   delay (2000);                              // .. 2 Sekunden warten
   read_DDram (3);                            // .. z.B. Zeile 3 im DDram lesen
                                              // Ende des Programms nach einmaligem Durchlauf
}
 
// ======================================================================================================
// einmalig, die Startbedingungen des Programms einstellen
void setup () {
   Wire.begin ();                             // Initialisierung der Wire-Bibliothek
   Wire.setClock (100000L);                   // I2C- Bus mit 100kHz
   init_LCD ();                               // Anzeige einrichten
   clear_display ();                          // Anzeige löschen
   
   ausgabetest ();                            // Aufruf des obigen Testprogramms
}
   
// wird die Funktion loop() entfernt, erscheint der Fehler:
// Fehler beim Kompilieren für das Board Arduino Nano
// --------------------------------------------------------
void loop() {
     // nix
}
 
 
// LCD Konfigurationsregister setzen
// ---------------------------------
void init_LCD () {
   Wire.beginTransmission (I2CadrLCD);
   Wire.write (0x00);                         // Kontrollbyte senden C0=0, RS=0, R/W=0, x xxxx
   Wire.write (0x2E);                         // Function Set:  0 0 1 DL=x – N=1, M=1, G=1, 0   => 0x2E
   Wire.write (0x0F);                         // Display control:   0 0 0 0 - 1 D=1, C=1, B=1   => 0x0F
   Wire.write (0x06);                         // Entry mode set:    0 0 0 0 - 0 1 I/D=0, S=1    => 0x06
   Wire.write (0x01);                         // Clear Display:     0 0 0 0 - 0 0 0 1           => 0x01
   Wire.endTransmission ();
   delay (20);
}
   
// Anzeige löschen, DDram auf Adresse 0
// (Cursor auf Position z=1, s=1)
// ------------------------------------
void clear_display () {
   Wire.beginTransmission (I2CadrLCD);
   Wire.write (0x00);                         // Kontrollbyte senden C0=0, RS=0, R/W=0, x xxxx
   Wire.write (0x02);                         // Return Home:   0 0 0 0 - 0 0 1 0     => 0x02
   Wire.endTransmission ();
}
   
// Text ausgeben
// Der Text wird in Zeile (z) und Spalte (s) ausgegeben
// ----------------------------------------------------
void print_TXT (byte z, byte s, String TXTstrg) {
   set_DDram (z,s);                           // Ausgabeposition im DDram setzen
   byte tl = 12-s+1;                          // Textlänge (tl) = 12 Ausgabestellen - eingerückte Spalten
   if (TXTstrg.length() < tl) tl=TXTstrg.length(); // Ausgabetext ist kürzer als auszugebende Textlänge
 
   Wire.beginTransmission (I2CadrLCD);
   Wire.write (0x40);                         // Kontrollbyte senden C0=0, RS=1, R/W=0, x xxxx
   for (int b=0; b < tl; b++) {
      Wire.write (0x80 + TXTstrg[b]);         // .. tl Zeichen des 0x80 Zeichensatzes ausgeben
   }
   Wire.endTransmission ();
}
   
// setzt die Ausgabeposition zeile= 1-3 und spalte= 1-12 im DDram
// Im Programm beginnen die Zeilen und Spalten mit 0, 1, 2 ..
// ungültige Werte werden ignoriert
// --------------------------------------------------------------
void set_DDram (byte z,byte s) {
   byte pos; z=z-1; s=s-1;                    // 1,2,3 .. zurücksetzen auf 0,1,2 ..
   if (z>2 || s>11) return;                   // angegebene Zeile größer 2, Spalte gößer 11
 
   Wire.beginTransmission (I2CadrLCD);
   Wire.write (0x00);                         // Kontrollbyte senden C0=0, RS=0, R/W=0, x xxxx
 
   if (z == 0) pos= 0x00+s;                   // Anfangsadresse Zeile 1 + Spalte
   if (z == 1) pos= 0x20+s;                   // Anfangsadresse Zeile 2 + Spalte
   if (z == 2) pos= 0x40+s;                   // Anfangsadresse Zeile 3 + Spalte
 
   Wire.write (0x80+pos);                     // DDram Adresse setzen: 1aaa aaaa
   Wire.endTransmission ();
}
   
// löscht die Zeile 1,2 od.3 mit Spaces
// ungültige Zeilenangaben werden ignoriert
// ------------------------------------------
void clr_line (byte z) {
   byte pos; z=z-1;
   if (z>2) return;
   Wire.beginTransmission (I2CadrLCD);
   Wire.write (0x00);                         // Kontrollbyte senden C0=0, RS=0, R/W=0, x xxxx
 
   if (z == 0) pos= 0x00;                     // Anfangsadressen der Zeilen im DDram
   if (z == 1) pos= 0x20;
   if (z == 2) pos= 0x40;
 
   Wire.write (0x80+pos);                     // Set DDram Adresse 1aaa aaaa
   Wire.endTransmission ();
 
   Wire.beginTransmission (I2CadrLCD);
   Wire.write (0x40);                         // Kontrollbyte senden C0=0, RS=1, R/W=0, x xxxx
   for (int b=0; b < 12; b++){
      Wire.write (B10100000);                 // .. 12 x Space in Zeile ausgebn
   }
   Wire.endTransmission ();
}
   
// Cursor ausschalten on=0 / einschalten on=1
// ------------------------------------------
void cursor_on (byte on) {
   if (on == 0) on = 0x0E;                    // Display control: 0 0 0 0 - 1 D=1, C=1, B=0 => 0x0E
   else           on = 0x0F;                  // Display control: 0 0 0 0 - 1 D=1, C=1, B=1 => 0x0F
   Wire.beginTransmission (I2CadrLCD);
   Wire.write (0x00);                         // Kontrollbyte senden C0=0, RS=0, R/W=0, x xxxx
   Wire.write (on);                           // Cursor aus oder ein
   Wire.endTransmission ();
}
 
 
// ======================================================================================================
// Diese Programmteile dürften für den Betrieb des LCD-Displays EAT123A von untergeodneter Bedeutung
// sein, da die Anzeige nur 3 Zeilen und je 12 Zeichen besitzt. Sie können als Test für die Benutzung
// des Bits C0 aufgefasst werden, sowie als Anhalt für den Befehl 'Wire.requestFrom(..)'
// Damit die Ausgaben auf dem seriellen Monitor der Entwicklungsumgebung funktioniert muß vor dem
// Aufruf von 'read_DDrami() die Zeile Serial.begin (9600); eingefügt sein.
 
 
// das Busy-Flag (BF) lesen
// die Schleife wird durchlaufen, solange das BF=1 ist.
// die Rückgabe ist der Wert des Address-Counters
// ----------------------------------------------------
byte readBF() {
   byte BF;
   Wire.beginTransmission (I2CadrLCD);
   Wire.write (0x20);                         // Kontrollbyte senden C0=0, RS=0, R/W=1, x xxxx
      do{
         Wire.requestFrom(I2CadrLCD,1);       // Schleife solange durchlaufen, bis das Bit DB7,
         BF = Wire.read();                    // das Busy-Flag 0 ist
      } while(BF>>7 == 1);
   Wire.endTransmission ();
   return BF;                                 // dann den Wert des address-counters zurückgeben
}
   
// liest den Inhalt der Zeile z des DDram
// jede der Zeilen 1-3 besteht aus 20 Zeichen
// von denen nur 12 angezeigt werden.
// ------------------------------------------
void read_DDram(byte z) {
   byte pos; z=z-1;
 
   if (z == 0) pos= 0x00;                     // Anfangsadressen der Zeilen im DDram
   if (z == 1) pos= 0x20;
   if (z == 2) pos= 0x40;
 
   byte anz=20;                               // max.Anzahl der zu lesenden Bytes einer Zeile
   byte value[anz];                           // Array für die gelesenen Werte
   char x=0;
 
   Wire.beginTransmission (I2CadrLCD);
   Wire.write (0x80);                         // Kontrollbyte senden C0=1, RS=0, R/W=0, x xxxx
   Wire.write (0x80+pos);                     // .. DDram-Adresse ab der gelesen werden soll
   Wire.write (0x60);                         // Kontrollbyte senden C0=0, RS=1, R/W=1, x xxxx
   Wire.endTransmission ();
 
   Wire.beginTransmission (I2CadrLCD);
   Wire.requestFrom (I2CadrLCD,anz);
   for (byte n= 0; n<anz; n++) {
      value[n] = Wire.read();
   }
Wire.endTransmission ();
   
   // ---------------------------------------------------------------------------------------------------
   // Ausgabe der gelesenen Werte auf dem seriellen Monitor
   Serial.print ("Zeile: ");
   Serial.println (z+1);                      // .. die Zeile
   for (byte n=0; n<anz; n++){
      Serial.print ("Adresse: 0x");
      Serial.print (n,HEX);                   // .. die Adresse des DDram
      Serial.print (" - Inhalt: 0x");
      Serial.print (value[n],HEX);            // .. deren Inhalt hexadezimal
      Serial.print (" - ASCII: ");
      if (value[n] == 0xA0) Serial.println("spc");
      else {x = value[n]-128;
         Serial.println (x);                  // .. deren Inhalt als ASCII-Zeichen
      }
   }
}