Raspberry Pi и Pi4J. Урок 7. Работа с LCD на базе HD44780

Информации о том, что из себя представляет LCD на базе HD44780, в интернете очень много. Даже на этом сайте две статьи на эту тему (первая и вторая). Однако в этой статье речь пойдет не о нём, а о библиотеках Pi4J, что позволяют работать с данным дисплеем из Java.

Pi4J предоставляет 3 библиотеки для этих целей:

  1. com.pi4j.wiringpi.Lcd — это библиотека, позволяющая получать доступ к жидкокристаллическим дисплеям с параллельным интерфейсом через GPIO пины. Все методы этого класса нативные, так как вызываются функции wiringPi напрямую. Грубо говоря — это библиотека lcd.h, но только на Java.
  2. com.pi4j.component.lcd.impl.GpioLcdDisplay — это ООП версия com.pi4j.wiringpi.Lcd, что удобнее использовать. Для записи данных на дисплей используются функции com.pi4j.wiringpi.Lcd.
  3. com.pi4j.component.lcd.impl.I2CLcdDisplay — это библиотека для работы с жидкокристаллическими дисплеями через I2C (IIC/TWI), а именно — адаптер на чипе PCF8574. В таком случае для управления дисплеем будет использоваться всего 2 провода вместо 6 или 10.

Pi4J предоставляет возможность работы с LCD из Java на Raspberry Pi, Banana Pi, Orange Pi, Nano Pi и Odroid. Все классы и интерфейсы находятся в пакетах com.pi4j.component.lcd.*; com.pi4j.wiringpi.*; и com.pi4j.gpio.extension.pcf.*.

Ниже представлены описания интерфейсов/классов и примеры программ.

Класс Lcd

Как я уже писал выше, эта библиотека аналогична «wiringPi». Ниже вы найдёте пример программы, которая показывает, как использовать эту библиотеку для отображения строк на ЖК-дисплее.

Все нативные методы класса Lcd:

public static native int lcdInit(int rows, int cols, int bits, int rs, int strb, int d0,
		int d1, int d2, int d3, int d4, int d5, int d6, int d7);
public static native void lcdHome(int handle);
public static native void lcdClear(int handle);
public static native void lcdDisplay(int handle, int state);
public static native void lcdCursor(int handle, int state);
public static native void lcdCursorBlink(int handle, int state);
public static native void lcdPosition(int handle, int x, int y);
public static native void lcdCharDef(int handle, int index, byte data[]);
public static native void lcdPutchar(int handle, byte data);
public static native void lcdPuts(int handle, String data);

Описание этих функций вы найдёте здесь.

Схема подключения LCD в 4-битном режиме

Подключение LCD 1602 HD44780 к Orange Pi в 4-битном режиме

Пример программы в 4-битном режиме

Прежде всего, мы должны выбрать платформу, иначе программа будет работать с ошибками или вообще не будет работать. В моем случае это Orange Pi PC.

PlatformManager.setPlatform(Platform.ORANGEPI);

Затем нам нужно инициализировать контроллер GPIO для работы с ним. Если он не может быть инициализирован, будет сгенерировано исключение.

if (Gpio.wiringPiSetup() != 0) {
  throw new Exception("An error has occurred and the initialization of the GPIO has failed");
}

После этого мы можем инициализировать экземпляр ЖК-дисплея.

int lcdHandle = Lcd.lcdInit(
    LCD_ROWS, /* количество строк */
    LCD_COLUMNS, /* количество символов */
    LCD_BITS, /* количество бит, используемых для связи с ЖК-дисплеем */
    LCD_RS, /* LCD бит RS */
    LCD_E, /* LCD бит Enable */
    LCD_D4, /* LCD бит данных 4 */
    LCD_D5, /* LCD бит данных 5 */
    LCD_D6, /* LCD бит данных 6 */
    LCD_D7, /* LCD бит данных 7 */
    0, 0, 0, 0);

Метод lcdInit генерирует идентификатор lcdHandle, который будет использоваться для связи именно с этим ЖК-дисплеем.

import com.pi4j.platform.Platform;
import com.pi4j.platform.PlatformManager;
import com.pi4j.wiringpi.Gpio;
import com.pi4j.wiringpi.Lcd;

public class WiringPiLcd4Bit {

  public final static int LCD_ROWS = 2;
  public final static int LCD_ROW_1 = 0;
  public final static int LCD_ROW_2 = 1;
  public final static int LCD_COLUMNS = 16;
  public final static int LCD_BITS = 4;

  public final static int LCD_RS = 4; /* RS - Выбор регистра */
  public final static int LCD_E = 5; /* E - Еnable (строб по спаду) */
  public final static int LCD_D4 = 21; /* D4 - бит данных */
  public final static int LCD_D5 = 22; /* D5 - бит данных */
  public final static int LCD_D6 = 23; /* D6 - бит данных */
  public final static int LCD_D7 = 24; /* D7 - бит данных */

  public static void main(String[] args) throws Exception {

    PlatformManager.setPlatform(Platform.ORANGEPI);

    if (Gpio.wiringPiSetup() != 0) {
      throw new Exception("An error has occurred and the initialization of the GPIO has failed");
    }

    int lcdHandle = Lcd.lcdInit(
        LCD_ROWS, /* количество строк */
        LCD_COLUMNS, /* количество символов */
        LCD_BITS, /* количество бит, используемых для связи с ЖК-дисплеем */
        LCD_RS, /* LCD бит RS */
        LCD_E, /* LCD бит Enable */
        LCD_D4, /* LCD бит данных 4 */
        LCD_D5, /* LCD бит данных 5 */
        LCD_D6, /* LCD бит данных 6 */
        LCD_D7, /* LCD бит данных 7 */
        0, 0, 0, 0);

    /* проверяет инициализацию LCD */
    if (lcdHandle == -1) {
      throw new Exception("LCD INIT FAILED");
    }

    Lcd.lcdClear(lcdHandle);
    Lcd.lcdPosition(lcdHandle, 0, LCD_ROW_1);
    Lcd.lcdPuts(lcdHandle, "site:micro-pi.ru");
    Lcd.lcdPosition(lcdHandle, 0, LCD_ROW_2);
    Lcd.lcdPuts(lcdHandle, "Hello, world!");
  }
}

Проверяем код:

  1. создаём java файл и вставляем код;
    nano WiringPiLcd4Bit.java
  2. компилируем файл;
    javac -classpath .:classes:/opt/pi4j/lib/'*' WiringPiLcd4Bit.java
  3. запускаем программу.
    sudo java -classpath .:classes:/opt/pi4j/lib/'*' WiringPiLcd4Bit

Интерфейс LCD

Интерфейс LCD содержит методы для передачи строк и символов на ЖК-дисплей. Интерфейс реализован в двух классах GpioLcdDisplay и I2CLcdDisplay, первый работает с GPIO, а второй работает с I2C контроллером PCF8574.

getRowCount() и getColumnCount()

Методы возвращают число строк и символов соответственно.

int getRowCount();
int getColumnCount();

clear()

Метод void clear() возвращает курсор в начало экрана, заодно стирая всё, что было на дисплее до этого. Метод void clear(int row) стирает один ряд, а void clear(int row, int column, int length) — только нужную часть текста.

void clear();
void clear(int row);
void clear(int row, int column, int length);

setCursorHome() и setCursorPosition()

Метод setCursorHome() устанавливает курсор в исходное положение; setCursorPosition() устанавливает положение курсора для последующего ввода текста.

void setCursorHome();
void setCursorPosition(int row);
void setCursorPosition(int row, int column);

write(…)

Записывает строку данных на ЖК-дисплей.

void write(String data);
void write(String data, Object...arguments);
void write(char[] data);
void write(byte[] data);
void write(char data);
void write(byte data);

write(int, …)

Печатает нужную строку на указанный ряд.

void write(int row, String data, LCDTextAlignment alignment);
void write(int row, String data, LCDTextAlignment alignment, Object...arguments);
void write(int row, String data);
void write(int row, String data, Object...arguments);
void write(int row, char[] data);
void write(int row, byte[] data);
void write(int row, char data);
void write(int row, byte data);

write(int, int, …)

Печатает нужную строку, начиная с указанной позиции.

void write(int row, int column, String data);
void write(int row, int column, String data, Object...arguments);
void write(int row, int column, char[] data);
void write(int row, int column, byte[] data);
void write(int row, int column, char data);
void write(int row, int column, byte data);

writeln(int, …)

Метод печатает текст на жидкокристаллическом индикаторе на указанный ряд, после переводит курсор в начало следующего.

void writeln(int row, String data);
void writeln(int row, String data, Object...arguments);
void writeln(int row, String data, LCDTextAlignment alignment);
void writeln(int row, String data, LCDTextAlignment alignment, Object...arguments);

Перечисление LCDTextAlignment

Это перечисление используется с методами отображения текста на ЖК-дисплее (write и writeln) для выравнивания текста.

  • ALIGN_CENTER — используется для размещения текста в середине экрана;
  • ALIGN_LEFT — для размещения текста слева от экрана;
  • ALIGN_RIGHT — для размещения текста справа.

Класс GpioLcdDisplay

Класс GpioLcdDisplay реализует интерфейс LCD для работы с дисплеем через GPIO. Конструктор класса используется для инициализации ЖК-дисплея 8-битном или 4-битном режиме:

public GpioLcdDisplay(int rows, int columns, Pin rsPin, Pin strobePin, Pin... dataPins)

Параметры:
int rows — количество строк;
int columns — количество символов;
Pin rsPin — пин выбора регистра;
Pin strobePin — пин строба;
Pin... dataPins — пины данных;

Схема подключения LCD в 8-битном режиме

Подключение LCD 1602 HD44780 к Orange Pi в 8-битном режиме

Пример инициализации в 8-битном режиме

import com.pi4j.component.lcd.impl.GpioLcdDisplay;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.OrangePiPin;
import com.pi4j.platform.Platform;
import com.pi4j.platform.PlatformManager;

public class GpioLcd8Bit {

  public final static int LCD_ROWS = 2;
  public final static int LCD_ROW_1 = 0;
  public final static int LCD_ROW_2 = 1;
  public final static int LCD_COLUMNS = 16;
  public final static int LCD_BITS = 4;

  public static void main(String[] args) throws Exception {
    PlatformManager.setPlatform(Platform.ORANGEPI);

    GpioController gpio = GpioFactory.getInstance();

    GpioLcdDisplay lcd = new GpioLcdDisplay(
        LCD_ROWS, /* число строк */
        LCD_COLUMNS, /* число символов */
        OrangePiPin.GPIO_07, /* LCD бит RS */
        OrangePiPin.GPIO_01, /* LCD бит Еnable */
        OrangePiPin.GPIO_04, /* LCD бит данных 0 */
        OrangePiPin.GPIO_05, /* LCD бит данных 1 */
        OrangePiPin.GPIO_11, /* LCD бит данных 2 */
        OrangePiPin.GPIO_21, /* LCD бит данных 3 */
        OrangePiPin.GPIO_22, /* LCD бит данных 4 */
        OrangePiPin.GPIO_23, /* LCD бит данных 5 */
        OrangePiPin.GPIO_24, /* LCD бит данных 6 */
        OrangePiPin.GPIO_25); /* LCD бит данных 7 */

    lcd.clear();
    Thread.sleep(1000);

    lcd.write(LCD_ROW_1, "The Pi4J Project");
    lcd.write(LCD_ROW_2, "site:micro-pi.ru");
    gpio.shutdown();
  }
}

Схема подключения LCD в 4-битном режиме

Подключение LCD 1602 HD44780 к Orange Pi в 4-битном режиме

Пример инициализации в 4-битном режиме

import com.pi4j.component.lcd.impl.GpioLcdDisplay;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.OrangePiPin;
import com.pi4j.platform.Platform;
import com.pi4j.platform.PlatformManager;

public class GpioLcd4Bit {

  public final static int LCD_ROWS = 2;
  public final static int LCD_ROW_1 = 0;
  public final static int LCD_ROW_2 = 1;
  public final static int LCD_COLUMNS = 16;
  public final static int LCD_BITS = 4;

  public static void main(String[] args) throws Exception {
    PlatformManager.setPlatform(Platform.ORANGEPI);

    GpioController gpio = GpioFactory.getInstance();

    GpioLcdDisplay lcd = new GpioLcdDisplay(
        LCD_ROWS, /* число строк */
        LCD_COLUMNS, /* число символов */
        OrangePiPin.GPIO_04, /* LCD бит RS */
        OrangePiPin.GPIO_05, /* LCD бит Еnable */
        OrangePiPin.GPIO_21, /* LCD бит данных 4 */
        OrangePiPin.GPIO_22, /* LCD бит данных 5 */
        OrangePiPin.GPIO_23, /* LCD бит данных 6 */
        OrangePiPin.GPIO_24); /* LCD бит данных 7 */

    lcd.clear();
    Thread.sleep(1000);

    lcd.write(LCD_ROW_1, "The Pi4J Project");
    lcd.write(LCD_ROW_2, "site:micro-pi.ru");
    gpio.shutdown();
  }
}

Класс I2CLcdDisplay

Класс I2CLcdDisplay — это второй класс, который реализует интерфейс LCD.java для передачи данных на ЖК-дисплей через протокол I2C. В этих случаях используются адаптеры на основе чипов PCF8574. В моем случае — это адаптер FC-113 на базе FCF8574AT, что имеет диапазон адресов от 38h до 3Fh.

Этот класс содержит дополнительные методы для включения и выключения подсветки ЖК-дисплея.

Схема подключения

Подключение LCD 1602 HD44780 к Orange Pi по I2C с использованием адаптера PCF8574
Если хотите подключить LCD к 5В, тогда необходимо использовать I2C преобразователя логических уровней 5-3.3В по линиям SDA и SCL.
Подключение LCD 1602 HD44780 к Orange Pi по I2C с использованием адаптера PCF8574 и I2C Преобразователя логических уровней 5-3.3В

Orange Pi Преобразователь PCF8574
LV/3.3В HV/5.0В
HV VCC
3.3В LV
GND GND GND GND
SDA.0 LV2 HV2 SDA
SCL.0 LV1 HV1 SCL

Пример программы

Эта программа инициализируется для работы с Orange Pi;

PlatformManager.setPlatform(Platform.ORANGEPI);

создает экземпляр класса I2CLcdDisplay. Стоит заметить, что бывают разные адаптеры на базе FCF8574AT и распиновка тоже разная;

I2CLcdDisplay lcd = new I2CLcdDisplay(
    LCD_ROWS, /* число строк */
    LCD_COLUMNS, /* число символов */
    I2CBus.BUS_0, /* I2C шина */
    PCF8574GpioProvider.PCF8574A_0x3F, /* I2C адрес */
    PCF8574Pin.GPIO_03.getAddress(), /* LCD бит подсветки */
    PCF8574Pin.GPIO_00.getAddress(), /* LCD бит RS */
    PCF8574Pin.GPIO_01.getAddress(), /* LCD бит RW */
    PCF8574Pin.GPIO_02.getAddress(), /* LCD бит Еnable */
    PCF8574Pin.GPIO_07.getAddress(), /* LCD бит данных 7 */
    PCF8574Pin.GPIO_06.getAddress(), /* LCD бит данных 6 */
    PCF8574Pin.GPIO_05.getAddress(), /* LCD бит данных 5 */
    PCF8574Pin.GPIO_04.getAddress()); /* LCD бит данных 4 */

записывает строку на ЖК-дисплей на первый ряд по центру;

lcd.write(LCD_ROW_1, "micro-pi.ru", LCDTextAlignment.ALIGN_CENTER);

выключает и включает подсветку;

lcd.setBacklight(false, true);
lcd.setBacklight(true, true);

и выводит текущее время;

while (true) {
  /* записывает строку на ЖК-дисплей: второй ряд по центру */
  lcd.writeln(LCD_ROW_2, formatter.format(new Date()), LCDTextAlignment.ALIGN_CENTER);
  Thread.sleep(1000);
}

Полный код программы:

import java.text.SimpleDateFormat;
import java.util.Date;

import com.pi4j.component.lcd.LCDTextAlignment;
import com.pi4j.component.lcd.impl.I2CLcdDisplay;
import com.pi4j.gpio.extension.pcf.PCF8574GpioProvider;
import com.pi4j.gpio.extension.pcf.PCF8574Pin;
import com.pi4j.io.i2c.I2CBus;
import com.pi4j.platform.Platform;
import com.pi4j.platform.PlatformManager;

public class I2cLcdPCF8574AT {

  public final static int LCD_ROWS = 2;
  public final static int LCD_ROW_1 = 0;
  public final static int LCD_ROW_2 = 1;
  public final static int LCD_COLUMNS = 16;

  public static void main(String[] args) throws Exception {
    PlatformManager.setPlatform(Platform.ORANGEPI);

    I2CLcdDisplay lcd = new I2CLcdDisplay(
        LCD_ROWS, /* число строк */
        LCD_COLUMNS, /* число символов */
        I2CBus.BUS_0, /* I2C шина */
        PCF8574GpioProvider.PCF8574A_0x3F, /* I2C адрес */
        PCF8574Pin.GPIO_03.getAddress(), /* LCD бит подсветки */
        PCF8574Pin.GPIO_00.getAddress(), /* LCD бит RS */
        PCF8574Pin.GPIO_01.getAddress(), /* LCD бит RW */
        PCF8574Pin.GPIO_02.getAddress(), /* LCD бит Еnable */
        PCF8574Pin.GPIO_07.getAddress(), /* LCD бит данных 7 */
        PCF8574Pin.GPIO_06.getAddress(), /* LCD бит данных 6 */
        PCF8574Pin.GPIO_05.getAddress(), /* LCD бит данных 5 */
        PCF8574Pin.GPIO_04.getAddress()); /* LCD бит данных 4 */

    /* очищает LCD */
    lcd.clear();
    Thread.sleep(1000);

    /* записывает строку на ЖК-дисплей: первый ряд по центру */
    lcd.write(LCD_ROW_1, "micro-pi.ru", LCDTextAlignment.ALIGN_CENTER);
    Thread.sleep(1000);

    /* выключает подсветку */
    lcd.setBacklight(false, true);
    Thread.sleep(1000);

    /* включает подсветку */
    lcd.setBacklight(true, true);

    SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");

    /* обновляет текущее время каждую секунду */
    while (true) {
      /* записывает строку на ЖК-дисплей: второй ряд по центру */
      lcd.writeln(LCD_ROW_2, formatter.format(new Date()), LCDTextAlignment.ALIGN_CENTER);
      Thread.sleep(1000);
    }
  }
}

Проверяем код:

  1. создаём java файл и вставляем код;
    nano I2cLcdPCF8574AT.java
  2. компилируем файл;
    javac -classpath .:classes:/opt/pi4j/lib/'*' I2cLcdPCF8574AT.java
  3. запускаем программу.
    sudo java -classpath .:classes:/opt/pi4j/lib/'*' I2cLcdPCF8574AT

Результат

Подключение LCD 1602 HD44780 к Orange Pi по I2C с использованием адаптера PCF8574 - Результат Подключение LCD 1602 HD44780 к Orange Pi по I2C с использованием адаптера PCF8574 - РезультатЕсли у Вас будут вопросы — можете задать их в комментариях.

Материалы

LCD Library (HD44780U)
PCF8574_PCF8574A.pdf
Sainsmart 16×2 I2C lcd

Похожие записи

Комментарии 3

  • По поводу подключения LCD по i2c. У вас подключение к плате без преобразования уровней. Разве GPIO Orange PI толерантны к 5В ой логике?

    • Вы правы, в действительности я подключил модуль к 3.3 В, а в схеме чуток ошибся и подключил к 5В. Я исправлю схему, чтобы не вести людей в заблуждении. Спасибо, что заметили и предупредили.

      Если присмотреться к фотографии, то видно, что чёрный провод от Vcc идёт к первому пину — 3.3В

Добавить комментарий для Serge Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *