Hitachi HD44780 Text Anzeigemodul unter Linux



/content/2021/display.jpg

Für ein Projekt verwende ich ein Text Anzeigmodul mit dem Hitachi HD44780 Chip. Diese Displays gibt es in verschiedenen Größen, üblich sind 2 Zeilen mit 16 Zeichen oder 4 Zeilen mit 20 Zeichen. Die letztere Variante wird auch unter dem Namen 2004a vertrieben. Diese Displays arbeiten mit 5V. Weil heutzutage die meisten Microcontroller und CPUs mit 3.3V oder weniger betrieben werden, wird so ein Display oft an einen I²C-Bus über eine I/O Erweiterung (ein sogenannter GPIO Extender) angeschlossen, die meisten davon mit einem PCF8574 Chip. Man kann die Displays und GPIO Extender separat oder zusammen kaufen, auflöten muss man das extender-Modul in jedem Fall selbst.

Das korrekte Vorgehen, so ein Display an einen 3.3V I²C Bus anzuschließen wäre über einen Pegelwandler. Es gibt aber einen Hardware-Hack wo man einfach die Pull-Up Widerstände auf dem PCF8574 Board entfernt (diese hängen direkt an +5V). Diese Änderung macht den GPIO Extender kompatibel mit 3.3V Installationen: Der im Datenblatt des PCF8574 angegebene minimale High-Pegel ist zwar 0.7 * VCC (was 3.5V bedeuten würde), in der Praxis funktioniert er aber einwandfrei mit 3.3V. Es sei darauf hingewiesen, dass die Nummern der Widerstände wie im Hardware-Hack angegeben (R5/R6) je nach Variante des PCF8574 Boards variieren. Ich habe die Nummern R8 und R9 gesehen sowie auch gar keine Beschriftung der Widerstände. Die Widerstände sind 4.7 kΩ, üblicherweise beschriftet mit 472 in der SMD Variante.

Dann habe ich untersucht, ob es einen Linux-Treiber für diese Displays gibt und habe einen in drivers/auxdisplay/hd44780.c im Kernel gefunden. Auf den ersten Blick schaut es so aus als ob dieser Treiber die Ansteuerung mit I²C über den PCF8574 I/O Extender nicht unterstützt. Also habe ich einen Treiber geschrieben und als Kernel-Patch eingereicht.

In der Diskussion (danke an Geert) hat sich dann herausgestellt, dass es einen Treiber für den PCF8574 im Kernel gibt (das hatte ich schon gesehen) und dass man den HD44780 Treiber mit der nötigen Device-Tree Magie so konfigurieren kann dass der PCF8574 Treiber für den I/O Extender verwendet wird. Die folgenden Device-Tree Beschwörungsformeln definieren ein Overlay das den PCF8574 mit seiner Standard I²C-Adress 0x27 konfiguriert und diesen dann für die I/Os des hd44780 Treibers verwendet:

// Note that on most boards another fragment must enable the I2C-1 Bus

/dts-v1/;
/plugin/;

/ {
        fragment@0 {
                target = <&i2c1>;
                __overlay__ {
                        #address-cells = <1>;
                        #size-cells = <0>;

                        pcf8574: pcf8574@27 {
                                compatible = "nxp,pcf8574";
                                reg = <0x27>;
                                gpio-controller;
                                #gpio-cells = <2>;
                        };

                };
        };

        fragment@1 {
                target-path = "/";
                __overlay__ {
                        hd44780 {
                                compatible = "hit,hd44780";
                                display-height-chars = <2>;
                                display-width-chars  = <16>;
                                data-gpios = <&pcf8574 4 0>,
                                             <&pcf8574 5 0>,
                                             <&pcf8574 6 0>,
                                             <&pcf8574 7 0>;
                                enable-gpios = <&pcf8574 2 0>;
                                rs-gpios = <&pcf8574 0 0>;
                                rw-gpios = <&pcf8574 1 0>;
                                backlight-gpios = <&pcf8574 3 0>;
                        };
                };
        };
};

Weil das nicht nur für mich nicht offensichtlich ist (in meiner Nachforschung habe ich mindestens zwei Linux-Treiber Implementierungen für die Kombination von HD44780 und PCF8574 ausserhalb des Linux-Kernels gefunden) habe ich einen Dokumentations-Patch eingereicht um das besser zu dokumentieren für Menschen die auch einen Linux-Treiber für diese Kombination suchen.

Es sei noch angemerkt, dass der Treiber für das Display Escape-Sequenzen verwendet um Spezialfunktionen des Displays (z.B. Ein/Ausschalten der Hintergrundbeleuchtung, löschen des Bildschirms, oder Benutzerdefinierte Bitmap-Zeichen) anzusteuern. Ich glaube diese sind nur im Source-Code in drivers/auxdisplay/charlcd.c dokumentiert.