Files
zh_160x_i2c/wiki_ru.md
T
2026-10-17 21:19:35 +03:00

14 KiB
Raw Blame History

Описание компонента zh_160x_i2c

Общие сведения

zh_160x_i2c — это драйвер для ESP-IDF, реализующий управление 16x2 и 16x4 LCD-дисплеями (HD44780-совместимыми) через I2C-расширитель PCF8574.

Компонент предоставляет высокоуровневый API для вывода текста, управления курсором, отображения индикатора прогресса и работы с числовыми данными на жидкокристаллических дисплеях.

Основные возможности

  1. Поддержка дисплеев 16x2 и 16x4 — автоматическое определение конфигурации экрана.
  2. 4-битный режим интерфейса — эффективная передача данных через линии D4–D7 (пин P4–P7 PCF8574).
  3. Вывод строк, целых и вещественных чисел — функции для форматированного вывода числовых данных.
  4. Отображение индикатора прогресса — 16-блочный прогресс-бар с настраиваемым процентом.
  5. Управление курсором — включение/выключение курсора и режима мерцания (blink).
  6. Построчная очистка — очистка произвольной строки дисплея.

Внутреннее устройство

Структура zh_160x_i2c_handle_t

Поле Тип Описание
zh_pcf8574_handle zh_pcf8574_handle_t * Указатель на управляющую структуру расширителя PCF8574
zh_160x_i2c_lcd_size zh_160x_i2c_lcd_size_t Конфигурация размера LCD (16x2 или 16x4)

Управляющая структура содержит ссылку на расширитель PCF8574 (который принадлежит вызывающей стороне) и текущую конфигурацию размера дисплея для расчёта адресов строк.

Управление памятью

Память под структуру zh_160x_i2c_handle_t выделяется функцией heap_caps_calloc() с флагом MALLOC_CAP_8BIT при вызове zh_160x_init(). Освобождение происходит через heap_caps_free() в функции zh_160x_deinit(), после чего указатель устанавливается в NULL для предотвращения use-after-free.

Адресация строк HD44780

HD44780-совместимые контроллеры используют нестандартную адресную карту строк:

Физическая строка Адрес DDRAM
0 0x00
1 0x40
2 0x10
3 0x50

Массив _lcd_row_addresses содержит эти адреса и используется функцией zh_160x_set_cursor() для корректного позиционирования курсора.

Протокол инициализации LCD

Инициализация follows HD44780 initialization protocol:

  1. Задержка 20 мс для стабилизации питания.
  2. Три команды 0x30 с импульсами Enable — перевод в 4-битный режим (последовательность «warm-up»).
  3. Команда 0x20 — установка 4-битного режима.
  4. Команда 0x28 — функция set: 4-бит, 2 строки, 5x8 точки.
  5. Команда 0x0C — display on, cursor off, blink off.
  6. Команда 0x01 — clear display.
  7. Команда 0x06 — entry mode: cursor increment, no shift.

API (интерфейс)

Инициализация и освобождение

Функция Описание
zh_160x_init() Инициализирует LCD-дисплей, выделяет и настраивает управляющую структуру, отправляет последовательность инициализации контроллеру LCD через расширитель PCF8574.
zh_160x_deinit() Освобождает выделенную память управляющей структуры и устанавливает указатель в NULL.

Позиционирование и очистка

Функция Описание
zh_160x_lcd_clear() Очищает весь экран LCD и перемещает курсор в домашнюю позицию (строка 0, столбец 0).
zh_160x_set_cursor() Устанавливает курсор в указанную позицию (строка и столбец). Для 16x2: строки 0–1, столбцы 0–15. Для 16x4: строки 0–3, столбцы 0–15.
zh_160x_clear_row() Очищает указанную строку (заполняет 16 пробелами) и возвращает курсор в начало строки.

Вывод данных

Функция Описание
zh_160x_print_char() Выводит строку символов в текущую позицию курсора. Курсор автоматически перемещается после каждого символа.
zh_160x_print_int() Преобразует целое число (signed 32-bit) в десятичную строку и выводит на дисплей.
zh_160x_print_float() Преобразует число с плавающей точкой в строку с указанным количеством знаков после запятой и выводит на дисплей.

Прогресс-бар и курсор

Функция Описание
zh_160x_print_progress_bar() Отображает 16-блочный прогресс-бар на указанной строке. Заполненные блоки отображаются как символ с кодом 0xFF (требует настройки CGRAM).
zh_160x_on_cursor() Включает курсор с опциональным режимом мерцания (blink).
zh_160x_off_cursor() Выключает курсор и режим мерцания.

Потокобезопасность

Компонент не является потокобезопасным. Все операции с LCD-дисплеем требуют внешних механизмов синхронизации (мьютексов, критических секций) при доступе из нескольких задач FreeRTOS. Управляющая структура zh_160x_i2c_handle_t не содержит внутренних примитивов синхронизации.

Алгоритмы

Отправка данных в 4-битном режиме

Команды и данные передаются в два этапа (старший и младший нибблы) через линии D4–D7:

  1. Отправка команды (_zh_160x_send_command) — старший ниббл команды записывается на шины с маской 0x08 (RS=0, P3=1), затем генерируется импульс Enable. Затем младший ниббл (сдвинутый на 4 бита) записывается с той же маской и снова импульс Enable.
  2. Отправка данных (_zh_160x_send_data) — аналогично, но с маской 0x09 (RS=1 для режима данных, P3=1).
  3. Импульс Enable (_zh_160x_pulse) — установка пина P2 в HIGH, задержка 1 мс, установка в LOW, задержка 1 мс. Этот импульс Latch-ит данные в LCD-контроллер.

Прогресс-бар

Процент прогресса конвертируется в количество заполненных блоков по формуле:

blocks = (progress * 16) / 100

Где progress — значение от 0 до 100. Заполненные блоки выводятся как 0xFF (сплошной блок), пустые — как пробелы.

Примеры использования

Базовый вывод текста

#include "zh_160x_i2c.h"

zh_pcf8574_handle_t *pcf8574_handle = NULL;
zh_160x_i2c_handle_t *lcd_160x_handle = NULL;

void app_main(void)
{
    // Настройка I2C-шины и инициализация PCF8574...
    zh_pcf8574_init_config_t config = ZH_PCF8574_INIT_CONFIG_DEFAULT();
    config.i2c_handle = i2c_bus_handle;
    config.i2c_address = 0x27;
    zh_pcf8574_init(&config, &pcf8574_handle);

    // Инициализация LCD 16x2
    zh_160x_init(&pcf8574_handle, &lcd_160x_handle, ZH_LCD_16X2);

    // Вывод текста на дисплей
    zh_160x_set_cursor(&lcd_160x_handle, 0, 0);
    zh_160x_print_char(&lcd_160x_handle, "Hello, LCD!");
    zh_160x_set_cursor(&lcd_160x_handle, 1, 0);
    zh_160x_print_char(&lcd_160x_handle, "ESP32 Ready");

    // Очистка и освобождение ресурсов
    vTaskDelay(5000 / portTICK_PERIOD_MS);
    zh_160x_lcd_clear(&lcd_160x_handle);
    zh_160x_deinit(&lcd_160x_handle);
}

Вывод числовых данных

// Вывод целого числа
int temperature = 25;
zh_160x_set_cursor(&lcd_160x_handle, 0, 0);
zh_160x_print_char(&lcd_160x_handle, "Temp: ");
zh_160x_print_int(&lcd_160x_handle, temperature);
zh_160x_print_char(&lcd_160x_handle, " C");

// Вывод числа с плавающей точкой (2 знака после запятой)
float voltage = 3.315f;
zh_160x_set_cursor(&lcd_160x_handle, 1, 0);
zh_160x_print_char(&lcd_160x_handle, "VCC: ");
zh_160x_print_float(&lcd_160x_handle, voltage, 2);
zh_160x_print_char(&lcd_160x_handle, " V");

Отображение прогресс-бара

// Прогресс-бар требует настройки CGRAM:
// DDRAM адрес 0xFF должен быть сопоставлен с пользовательским символом (CGRAM pattern 7)

for (uint8_t i = 0; i <= 100; i += 10)
{
    zh_160x_set_cursor(&lcd_160x_handle, 0, 0);
    zh_160x_print_char(&lcd_160x_handle, "Progress: ");
    zh_160x_print_int(&lcd_160x_handle, i);
    zh_160x_print_char(&lcd_160x_handle, "%");
    zh_160x_print_progress_bar(&lcd_160x_handle, 1, i);
    vTaskDelay(500 / portTICK_PERIOD_MS);
}

zh_160x_lcd_clear(&lcd_160x_handle);
zh_160x_deinit(&lcd_160x_handle);

Логирование

Компонент использует ESP-IDF логирование с тегом "zh_160x_i2c".

esp_log_level_set("zh_160x_i2c", ESP_LOG_ERROR);

Для включения подробного логирования установите уровень ESP_LOG_DEBUG.

Ошибки

Код Описание
ESP_OK Успешное выполнение
ESP_ERR_INVALID_ARG Неверный аргумент (NULL-указатель, недопустимый размер дисплея, координаты вне диапазона)
ESP_ERR_INVALID_STATE LCD уже инициализирован (повторная инициализация без деинициализации)
ESP_ERR_NO_MEM Не удалось выделить память под управляющую структуру
ESP_FAIL Ошибка записи/чтения через PCF8574 или сбой последовательности инициализации

Ограничения

  1. Зависимость от компонента zh_pcf8574 — требуется установка и инициализация драйвера PCF8574 перед использованием LCD.
  2. Буфер 16 символов — функция zh_160x_print_float() использует внутренний буфер фиксированной длины; длинные числа могут быть усечены.
  3. Отсутствие потокобезопасности — все операции с LCD требуют внешней синхронизации при работе из нескольких задач FreeRTOS.
  4. Прогресс-бар требует CGRAM — для отображения заполненных блоков символ с кодом 0xFF должен быть настроен как пользовательский символ в CGRAM (паттерн 7 HD44780).
  5. Один I2C-адрес — компонент рассчитан на один LCD-модуль на шину; множественные дисплеи требуют дополнительных расширителей или мультиплексирования.

Требования для сборки

  • ESP-IDF v5.0 или новее
  • Компонент zh_pcf8574 (зависимость, устанавливается автоматически через idf_component_manager)
  • FreeRTOS (входит в состав ESP-IDF)
  • Настройка CONFIG_FREERTOS_HZ=1000 в menuconfig

Установка

cd ваш_проект/components
git clone https://github.com/aZholtikov/zh_160x_i2c
#include "zh_160x_i2c.h"