Halli Hallo!
In diesem Tutorial geht es um das ansteuern eines LCD Displays mit HD44780 Controller über ein I2C Modul am Raspberry PI Model B. Ich verwende das Pollin L2C Selberlöt-Modul (Link).
Also für dieses Tuorial benötigt Ihr:
- Raspberry PI Model B
- Ein HD44780 LCD Display (2x16, 2x20, 4x16, 4x20)
- Ein I2C Modul LCD Modul
- Laborsteckkarte (Breadboard)
- 5 Jumperwire
Als Betriebsystem auf dem PI bietet sich Raspbian oder eine abgespeckte Version an (z.B. Moebius)
Zudem sollte eine funktionierende Entwicklungsumgebung installiert sein. Ich werde in diesem Tutorial zum einen auf C (GCC) setzen und zum anderen auf Basic (FreeBasic). Um mit den GPIO's zu sprechen sollte zudem noch wiringPi (Link) installiert sein.
Wer das Tutorial mit FreeBasic umsetzen möchte sollte sich vorher mein anderes Tutorial zum Thema FreeBasic und wiringPi einrichten anschauen (Link)
Also legen wir Los
Im grunde nichts schweres. Am Pollin Modul ist eine 4 Polige Anschlussklemme die wir mit SDA, SCL, +5V und GND vom Pi bedienen. Auf dem Modul befinden sich 3 3-Polige Steckbrücken über die wir die I2C Adresse per Jumper setzen können (für den Fall das wir mehrere Displays nutzen oder die Basisadresse schon vergeben ist), für dieses Tutorial ist es vollkommen egal wie wir Jumpern.
Es bietet sich an den R/W Pin des Displays (5) auf LOW zu ziehen damit der Display dauerhaft im Schreibmodus ist. Das ist sicherer um den Pi vor beschädigung durch die 5V Spannung abzusichern.
Das wars schon zum Aufbau.
Randbemerkung:
Wer sich gerne erstmal nur mit dem Display beschäftigen möchte findet unter folgendem Link ein schönes Beispiel wie man das Display ganz ohne uC ansprechen kann.
2. Die Adresse des Displays ermitteln.
Zum ausfindig machen der Adresse des PCF8574 (der 8-Bit Portexpander den das Modul nutzt) nutzen wir die i2c-tools.
Sollten diese noch installiert sein kann man das ganz einfach per befehl Installieren.
Ist das geschehen kann man per
die Adresse ausfindig machen. Die Ausgabe sollte in etwa so aussehen (Fremdes Bild)
Aus dieser Tabelle lässt sich der wert 0x48 (&H48) ablesen, welches die Adresse unseres Moduls am I2C Bus ist.
3. Den Display ansteuern
Ich werde in diesem Abschnitt nur bedingt auf die Programmierung eingehen und eher erklären was die einzelnen Abschnitte bewirken. Sollten Fragen aufkommen, werde ich natürlich so gut es geht hier im Thread antworten.
3.1 Die C Version
Wir erstellen uns ein neues Arbeitsverzeichnis und erstellen die lcd.c in eben diesem.
lcd.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wiringPi.h>
#include <pcf8574.h>
#define RS_CMD 0
#define RS_DATA 1
#define BACKLIGHT_ON 0
#define BACKLIGHT_OFF 1
#define LC_SIG_RESET 0x03
#define LC_SIG_4BINP 0x02
#define LC_SIG_4BMODE 0x28
#define LC_SIG_DON 0x0C
#define LC_SIG_SHOWCURSOR 0x02
#define LC_SIG_CURSORBLINK 0x01
#define LC_SIG_NORMALMODE 0x06
#define LC_CMD_CLEAR 0x01
/* 2 Zeilen Display */
#define LC_LINE1 0x80
#define LC_LINE2 0x90
/* 4 Zeilen Display */
/*
#define LC_LINE1 0x80
#define LC_LINE2 0xC0
#define LC_LINE3 0x90
#define LC_LINE4 0xD0
*/
void send4BitCmd(int RS, char Command) {
int i;
digitalWrite(104, RS);
digitalWrite(106, 1);
for (i = 4; i < 8; ++i) {
digitalWrite((107 - i),(Command >> 11 - i) & 1);
}
digitalWrite(106, 0);
digitalWrite(106, 1);
for (i = 0; i < 4; ++i) {
digitalWrite((103 - i),(Command >> 3 - i) & 1);
}
digitalWrite(106, 0);
}
void sendNibble(int RS,char Command) {
int i;
digitalWrite(104, RS);
digitalWrite(106, 1);
for (i = 0; i < 4; ++i) {
digitalWrite((100 + i),(Command >> i) & 1);
}
digitalWrite(106, 0);
}
void initLCDisplay() {
//Soft Reset Signal
digitalWrite(105, 0);
sendNibble(RS_CMD,LC_SIG_RESET);
sendNibble(RS_CMD,LC_SIG_RESET);
sendNibble(RS_CMD,LC_SIG_RESET);
sendNibble(RS_CMD,LC_SIG_4BINP); //Set 4 Bit Input
send4BitCmd(RS_CMD,LC_SIG_4BMODE); //Set 4 Bit Mode
send4BitCmd(RS_CMD,LC_SIG_DON); //Display on hide cursor no blinking
send4BitCmd(RS_CMD,LC_CMD_CLEAR); //Clear
send4BitCmd(RS_CMD,LC_SIG_NORMALMODE); //Entry Mode, Increment cursor position, No display shift
}
void sendBacklight(int Switch) {
digitalWrite(107, Switch);
}
void sendPosition(int Line, int Col) {
send4BitCmd(RS_CMD, Line + Col);
}
void sendText(char *source) {
int i = 0;
for (i;i < (int)strlen(source); i++)
{
send4BitCmd(RS_DATA, source);
}
}
int main (void) {
printf ("RasPi LCD\n");
if (wiringPiSetup () == -1) //wiringPi Initialisieren
return 1;
if (pcf8574Setup (100, 0x48) == -1) //Virtuelle GPIO's bereitstellen PCF Pin 0 = WiringPi GPIO 100 usw
return 1; //0x48 = die vorher ermittelte Adresse
initLCDisplay();
sendBacklight(BACKLIGHT_ON);
send4BitCmd(RS_CMD,LC_CMD_CLEAR);
for (; ; ) {
sendPosition(LC_LINE1, 0);
sendText("****************");
sendPosition(LC_LINE2, 0);
sendText("Hallo");
sendPosition(LC_LINE3, 10);
sendText("Welt");
sendPosition(LC_LINE4, 0);
sendText("****************");
}
}
Alles anzeigen
Erstellen könnt ihr das ganze mit
Aber gehen wir zuerst einmal auf den Code ein.
Wir binden zuerst alle benötigten Header ein, insbesondere wiringPi. Im anschluss definieren wir uns ein paar Konstanten um das Arbeiten mit dem display zu erleichtern. Das HD hat 2 Modi zum einen den 8-Bit modus und den 4-Bit modus. Der 8-Bit modus wird in den meißten fällen einfach ignoriert da er nicht wirklich schneller ist aber im endeffekt mehr Pins benötigt.
Nehmen wir zum Beisiel den Clear Befehl
Hex 01 Dez 01 Bin 00000001
Im 4 Bit Modus wird nun die 0000 0001 aufgebrochen und als jewails 4 Bit Nibble gesendet.
Eine kleine übersicht der wichtigsten Befehle gibt es hier: Link
Aber zurück zum Code.
In unserer Hauptprozedur (main) Initialisieren wir zuerst wiringPi an sich (und danach Registrieren wir uns unsere Virtuellen GPIO's)
Als nächstes springen wir in die initLCDisplay Prozedur und senden dem LCDController ein paar Kommandos.