Информации о том, что из себя представляет LCD на базе HD44780, в интернете очень много. Даже на этом сайте две статьи на эту тему (первая и вторая). Однако в этой статье речь пойдет не о нём, а о библиотеках Pi4J, что позволяют работать с данным дисплеем из Java.
Pi4J предоставляет 3 библиотеки для этих целей:
com.pi4j.wiringpi.Lcd
— это библиотека, позволяющая получать доступ к жидкокристаллическим дисплеям с параллельным интерфейсом через GPIO пины. Все методы этого класса нативные, так как вызываются функции wiringPi напрямую. Грубо говоря — это библиотекаlcd.h
, но только на Java.com.pi4j.component.lcd.impl.GpioLcdDisplay
— это ООП версияcom.pi4j.wiringpi.Lcd
, что удобнее использовать. Для записи данных на дисплей используются функцииcom.pi4j.wiringpi.Lcd
.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-битном режиме
Пример программы в 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!"); } }
Проверяем код:
- создаём java файл и вставляем код;
nano WiringPiLcd4Bit.java
- компилируем файл;
javac -classpath .:classes:/opt/pi4j/lib/'*' WiringPiLcd4Bit.java
- запускаем программу.
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-битном режиме
Пример инициализации в 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-битном режиме
Пример инициализации в 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 к 5В, тогда необходимо использовать I2C преобразователя логических уровней 5-3.3В по линиям SDA и SCL.
Orange Pi | Преобразователь | PCF8574 | |
---|---|---|---|
LV/3.3В | HV/5.0В | ||
5В | — | 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); } } }
Проверяем код:
- создаём java файл и вставляем код;
nano I2cLcdPCF8574AT.java
- компилируем файл;
javac -classpath .:classes:/opt/pi4j/lib/'*' I2cLcdPCF8574AT.java
- запускаем программу.
sudo java -classpath .:classes:/opt/pi4j/lib/'*' I2cLcdPCF8574AT
Результат
Если у Вас будут вопросы — можете задать их в комментариях.
Материалы
LCD Library (HD44780U)
PCF8574_PCF8574A.pdf
Sainsmart 16×2 I2C lcd
По поводу подключения LCD по i2c. У вас подключение к плате без преобразования уровней. Разве GPIO Orange PI толерантны к 5В ой логике?
Вы правы, в действительности я подключил модуль к 3.3 В, а в схеме чуток ошибся и подключил к 5В. Я исправлю схему, чтобы не вести людей в заблуждении. Спасибо, что заметили и предупредили.
Если присмотреться к фотографии, то видно, что чёрный провод от Vcc идёт к первому пину — 3.3В