Почему квадраты на дисплее 1602

12 августа 2018

В группах ВК по тематике Arduino часто встречаю вопросы о дисплеях 1602 (и подобных), построенных на контроллере HD44780. Один из них — почему на дисплее отображаются квадраты вместо того, что запрограммировано в скетче. И чтобы не повторять каждый раз всё это в комментариях, я решил написать эту статейку.

HD44780 (а также совместимый с ним KS0066) — контроллер монохромных жидкокристаллических знакосинтезирующих дисплеев с параллельным 4- или 8-битным интерфейсом. Разработан фирмой Hitachi. Управляющий интерфейс и протокол являются де-факто стандартом для такого типа дисплеев. Эти контроллеры были фактически монополистами на рынке в 90-е годы.

На базе этого контроллера выпускалось огромное количество моделей с различным конструктивом и разрешением, начиная с 8×1 (восемь символов в одной строке), и заканчивая 40×4 (содержащих два независимых управляющих чипа). Часто встречаются 16×2 и 20×4, а также некоторые другие.

Википедия

Квадраты это не неисправность дисплея, а вполне адекватная его реакция на отсутствие инициализации. Своеобразный self-test. Отсутствовать инициализация может по нескольким причинам. Но для начала надо вспомнить, какие типы подключения бывают у дисплеев этого формфактора.

В этом случае между дисплеем и МК идёт шина из, как минимум, шести проводов (не считая питания):

Код для Arduino в этом случае выглядит примерно так:

#include <liquidcrystal.h>
 
//Создаем объект для работы с дисплеем.
//При создании указываем номера портов
//в порядке RS, E, DB4, DB5, DB6, DB7
LiquidCrystal lcd(12, 10, 5, 4, 3, 2);
 
void setup()
{
  //Выставлем число столбцов и строк
  lcd.begin(16, 2);
  //Выводим текст
  lcd.print("hello, world!");
}
 
void loop()
{
  lcd.setCursor(0, 1);
  lcd.print(millis()/1000);
}

Причины отображения квадратов:

  • Плохой контакт или неправильное подключение проводов (не те пины или перепутан порядок);
  • Неправильно указаны номера пинов в коде LiquidCrystal lcd(12, 10, 5, 4, 3, 2);

Исправление ошибки сводится к проверке качества пайки контактов, а также соответствия пинов в коде.

Здесь используется всего два пина для подключения. И эти пины жёстко фиксированы:

  • Arduino Uno, Arduino Ethernet — A4 (SDA), A5 (SCL)
  • Arduino Mega2560 — 20 (SDA), 21 (SCL)
  • Arduino Leonardo — 2 (SDA), 3 (SCL)
  • Arduino Due — 20 (SDA), 21 (SCL)

На самом же дисплее уже впаян конвертор с I2C на HD44780, который по сути представляет из себя обычный I2C-расширитель на базе чипа PCF8574. Особенность шины в том, что по двум проводам можно параллельно подключить множество различных устройств. Каждое устройство имеет уникальный (в пределах одной шины) адрес, который либо жёстко установлен производителем, либо может менять в определённых пределах с помощью перемычек или джамперов:

Адрес для PCF8574 можно посмотреть по таблице:

Вход A2 Вход A1 Вход A0 Адрес DEC Адрес HEX
0 0 0 32 0x20
0 0 1 33 0x21
0 1 0 34 0x22
0 1 1 35 0x23
1 0 0 36 0x24
1 0 1 37 0x25
1 1 0 38 0x26
1 1 1 39 0x27

Есть ещё PCF8574A. Для них адресация немного другая:

Вход A2 Вход A1 Вход A0 Адрес DEC Адрес HEX
0 0 0 56 0x38
0 0 1 57 0x39
0 1 0 58 0x3A
0 1 1 59 0x3B
1 0 0 60 0x3C
1 0 1 61 0x3D
1 1 0 62 0x3E
1 1 1 63 0x3F

Код при подключении по I2C обычно выглядит примерно так:

#include <wire.h>
#include <liquidcrystal_i2c.h>
 
LiquidCrystal_I2C lcd(0x20,16,2); // установка адреса и размера дисплея
 
void setup()
{
  lcd.init(); // инициализация дисплея
 
  lcd.backlight();
  lcd.print("Hello, world!");
}
 
void loop()
{
}

Но есть ещё одна версия библиотеки, в которой указывается не только адрес дисплея, но и порядок подключения контактов дисплея к контактам чипа PCF8574. Тогда код выглядит так:

#include <wire.h>
#include <liquidcrystal_i2c.h>
 
// Установка адреса и пинов I2C чипа, используемых для LCD подключения:
// addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
 
void setup()
{
  lcd.begin(16,2); // инициализация дисплея и указание его размера
 
  lcd.backlight();
  lcd.print("Hello, world!");
}
 
void loop()
{
}

Обратите внимание на отличия в объявлении объекта дисплея и инициализации. И всё было бы хорошо, но разные дисплеи иногда имеют разный порядок подключения контактов между собственно самим дисплеем и чипом PCF8574. Я лично встречал два варианта. Первый указан в коде выше. Второй способ объявления выглядит так:

LiquidCrystal_I2C lcd(0x27, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE);

Соответственно возможны следующие причины появления квадратов:

  1. Плохой контакт или неправильное подключение проводов (перепутаны местами SDA и SCL);
  2. Неправильно указано соответствие пинов дисплея и I2C чипа в коде LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
  3. Неправильно указан адрес дисплея.

Порядок поиска неисправности в данном случае такой:

  1. Проверить правильность подключения SDA и SCL;
  2. Запустить сканер шины I2C: [drain file 98 url I2C scanner] ([drain file 98 size]);
  3. Если сканер выдал информацию об адресе устройства, то сверяем его с тем, который указан в скетче. Если сканер «молчит», то возвращаемся к первому пункту или делаем вывод о неисправности I2C модуля на дисплее;
  4. Пробуем менять в коде комбинации пинов (соответствия дисплей — I2C). Два варианта я привёл выше. Есть ли ещё другие — не знаю.

Иногда встречаются советы покрутить контрастность. На самом деле это не поможет, так как если вы видите отчётливо верхние квадраты, но не видите нижние (как на фото в статье) — значит контрастность УЖЕ настроена нормально.

  • arduino/pochemu_kvadraty_na_displee_1602.txt
  • Последнее изменение: 21.01.2026 15:19
  • r0wbh