Files
zh_160x_i2c/WIKI_RU.md
T

24 KiB
Raw Blame History

zh_160x_i2c - Компонент LCD 1602A/1604A через I2C (PCF8574) для ESP-IDF

Содержание


Обзор

zh_160x_i2c — это легковесный компонент ESP-IDF для управления LCD-дисплеями 1602A и 1604A через интерфейс I2C с использованием расширителей ввода-вывода PCF8574(A). Этот компонент упрощает процесс отображения текста, чисел и индикаторов прогресса на символьных LCD-модулях, предоставляя простой и интуитивно понятный API.

Компонент разработан специально для микроконтроллеров ESP32 и использует драйвер I2C-мастера ESP-IDF и FreeRTOS для оптимальной производительности во встраиваемых системах.


Возможности

  1. [Простой API]: Удобные функции для распространенных операций с LCD
  2. [Интерфейс I2C]: Использует только 2 GPIO-пина (SCL и SDA) через расширитель PCF8574
  3. [Поддержка 1602A и 1604A]: Поддерживает LCD-модули 16x2 и 16x4
  4. [Множественные LCD]: До 16 LCD-модулей на одной шине I2C
  5. [Отображение текста]: Вывод строк, целых чисел и чисел с плавающей точкой
  6. [Управление курсором]: Включение/выключение курсора с опциональным миганием
  7. [Индикатор прогресса]: Отображение индикаторов прогресса на LCD
  8. [Операции со строками]: Очистка конкретных строк
  9. [Оптимизировано под ESP-IDF]: Использует драйвер I2C-мастера ESP-IDF и FreeRTOS

Установка

Перейдите в каталог компонентов вашего проекта:

cd ../ваш_проект/components

Клонируйте репозиторий:

git clone https://github.com/aZholtikov/zh_160x_i2c

В вашем приложении подключите заголовочный файл:

#include "zh_160x_i2c.h"

Компонент будет автоматически собран вместе с вашим проектом.

Обязательные настройки в menuconfig

Для корректной работы компонента включите следующие настройки в menuconfig:

CONFIG_FREERTOS_HZ=1000
CONFIG_I2C_ISR_IRAM_SAFE
CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM

Справочник API

Типы данных

zh_160x_i2c_handle_t

typedef struct _zh_160x_i2c_handle_t zh_160x_i2c_handle_t;

Непрозрачный дескриптор LCD-дисплея 160x I2C. Внутренняя структура, содержащая дескриптор расширителя PCF8574 и текущую конфигурацию размера LCD.


zh_160x_i2c_lcd_size_t

typedef enum
{
    ZH_LCD_16X2 = 0, /*!< Размер LCD 16x2 */
    ZH_LCD_16X4,     /*!< Размер LCD 16x4 */
    ZH_LCD_NUM_MAX
} zh_160x_i2c_lcd_size_t;

Перечисление поддерживаемых размеров LCD-дисплеев.

Значение Описание
ZH_LCD_16X2 LCD размером 16x2 (2 строки по 16 символов)
ZH_LCD_16X4 LCD размером 16x4 (4 строки по 16 символов)

zh_160x_init()

Инициализирует LCD-дисплей 160x.

Выделяет и настраивает дескриптор LCD, затем отправляет последовательность инициализации на контроллер LCD через расширитель I2C PCF8574. Настраивает 4-битный режим и устанавливает параметры дисплея по умолчанию.

Параметры:

  • expander - Указатель на дескриптор расширителя PCF8574. Не должен быть NULL
  • handle - Выходной указатель для нового выделенного дескриптора LCD. Должен быть NULL
  • size - Размер LCD (ZH_LCD_16X2 или ZH_LCD_16X4)

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL указатель или неверный размер)
  • ESP_ERR_INVALID_STATE - Дескриптор уже инициализирован
  • ESP_ERR_NO_MEM - Ошибка выделения памяти
  • ESP_FAIL - Сбой последовательности инициализации LCD

Пример:

zh_pcf8574_handle_t *lcd_expander = NULL;
zh_160x_i2c_handle_t *lcd_handle = NULL;
zh_pcf8574_init_config_t config = ZH_PCF8574_INIT_CONFIG_DEFAULT();
config.i2c_handle = i2c_bus_handle;
config.i2c_address = 0x27;
esp_err_t err = zh_pcf8574_init(&config, &lcd_expander);
if (err != ESP_OK) {
    // Обработка ошибки
}
err = zh_160x_init(&lcd_expander, &lcd_handle, ZH_LCD_16X2);
if (err != ESP_OK) {
    // Обработка ошибки
}

Примечание:

Перед инициализацией LCD необходимо инициализировать расширитель PCF8574.


zh_160x_lcd_clear()

Очищает экран LCD и перемещает курсор в домашнюю позицию.

Отправляет команду очистки LCD (0x01) для стирания всего отображаемого текста и сброса курсора в верхний левый угол (строка 0, столбец 0).

Параметры:

  • handle - Указатель на дескриптор LCD. Не должен быть NULL

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL handle)
  • ESP_FAIL - Ошибка отправки команды

zh_160x_set_cursor()

Устанавливает курсор в указанную позицию на LCD.

Перемещает курсор в указанную строку и столбец. Для дисплеев 16x2: строки 0–1, столбцы 0–15. Для дисплеев 16x4: строки 0–3, столбцы 0–15.

Параметры:

  • handle - Указатель на дескриптор LCD. Не должен быть NULL
  • row - Номер строки (0–1 для 16x2, 0–3 для 16x4)
  • col - Номер столбца (0–15)

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL handle или координаты вне диапазона)
  • ESP_FAIL - Ошибка отправки команды

Примечание:

Адресация строк: строка 0 = 0x00, строка 1 = 0x40, строка 2 = 0x10, строка 3 = 0x50.


zh_160x_print_char()

Выводит строку на LCD в текущую позицию курсора.

Передаёт каждый символ строки, завершающейся нулём, на LCD в 4-битном режиме. Курсор автоматически перемещается после каждого символа.

Параметры:

  • handle - Указатель на дескриптор LCD. Не должен быть NULL
  • str - Указатель на null-terminated строку для отображения. Не должен быть NULL

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL handle или str)
  • ESP_FAIL - Ошибка передачи символа

zh_160x_print_int()

Выводит целое число на LCD в текущую позицию курсора.

Преобразует целое число в десятичную строку и отображает её. Поддерживает отрицательные числа (максимум 11 цифр плюс знак).

Параметры:

  • handle - Указатель на дескриптор LCD. Не должен быть NULL
  • num - Целочисленное значение для отображения

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL handle)
  • ESP_FAIL - Ошибка преобразования строки или печати

zh_160x_print_float()

Выводит число с плавающей точкой на LCD в текущую позицию курсора.

Преобразует значение с плавающей точкой в строку с указанной точностью десятичных знаков и отображает её.

Параметры:

  • handle - Указатель на дескриптор LCD. Не должен быть NULL
  • num - Значение с плавающей точкой для отображения
  • precision - Количество знаков после запятой (0–6 рекомендуется)

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL handle)
  • ESP_FAIL - Ошибка преобразования строки или печати

zh_160x_print_progress_bar()

Отображает индикатор прогресса в указанной строке LCD.

Отрисовывает 16-блочный индикатор прогресса с использованием пользовательского символа (0xFF). Заполненные блоки представляют процент прогресса, пустые блоки показывают остаток.

Параметры:

  • handle - Указатель на дескриптор LCD. Не должен быть NULL
  • row - Номер строки (0–1 для 16x2, 0–3 для 16x4)
  • progress - Процент прогресса (0–100)

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL handle, row вне диапазона или progress > 100)
  • ESP_FAIL - Ошибка установки курсора или печати символов

zh_160x_clear_row()

Очищает указанную строку на LCD.

Перемещает курсор в начало указанной строки и заполняет все 16 позиций пробелами для стирания содержимого. Курсор остаётся в начале очищенной строки.

Параметры:

  • handle - Указатель на дескриптор LCD. Не должен быть NULL
  • row - Номер строки (0–1 для 16x2, 0–3 для 16x4)

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL handle или row вне диапазона)
  • ESP_FAIL - Ошибка установки курсора или печати символов

zh_160x_on_cursor()

Включает курсор с опциональным режимом мигания.

Включает курсор и при необходимости активирует мигание. Команда 0x0F включает курсор с миганием, 0x0E включает курсор без мигания.

Параметры:

  • handle - Указатель на дескриптор LCD. Не должен быть NULL
  • blink - Если true, включается мигающий курсор; если false — статичный курсор

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL handle)
  • ESP_FAIL - Ошибка отправки команды

zh_160x_off_cursor()

Отключает курсор и отключает мигание.

Отправляет команду 0x0C для отключения курсора и мигания курсора.

Параметры:

  • handle - Указатель на дескриптор LCD. Не должен быть NULL

Возвращает:

  • ESP_OK - Успех
  • ESP_ERR_INVALID_ARG - Неверный аргумент (NULL handle)
  • ESP_FAIL - Ошибка отправки команды

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

Базовый пример: Одиночный LCD-дисплей

#include "zh_160x_i2c.h"

#define I2C_PORT (I2C_NUM_MAX - 1)

zh_pcf8574_handle_t *lcd_expander = NULL;
zh_160x_i2c_handle_t *lcd_handle = NULL;

void app_main(void)
{
    esp_log_level_set("zh_160x_i2c", ESP_LOG_ERROR);
    esp_log_level_set("zh_pcf8574", ESP_LOG_ERROR);
    esp_log_level_set("zh_vector", ESP_LOG_ERROR);
    i2c_master_bus_config_t i2c_bus_config = {
        .clk_source = I2C_CLK_SRC_DEFAULT,
        .i2c_port = I2C_PORT,
        .scl_io_num = GPIO_NUM_22,
        .sda_io_num = GPIO_NUM_21,
        .glitch_ignore_cnt = 7,
        .flags.enable_internal_pullup = true,
    };
    i2c_master_bus_handle_t i2c_bus_handle = NULL;
    i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle);
    zh_pcf8574_init_config_t config = ZH_PCF8574_INIT_CONFIG_DEFAULT();
    config.i2c_handle = i2c_bus_handle;
    config.i2c_address = 0x27;
    esp_err_t err = zh_pcf8574_init(&config, &lcd_expander);
    if (err != ESP_OK) {
        return;
    }
    err = zh_160x_init(&lcd_expander, &lcd_handle, ZH_LCD_16X2);
    if (err != ESP_OK) {
        return;
    }
    // Отображение текста
    zh_160x_set_cursor(&lcd_handle, 0, 0);
    zh_160x_print_char(&lcd_handle, "LCD 160X");
    zh_160x_set_cursor(&lcd_handle, 1, 0);
    zh_160x_print_char(&lcd_handle, "Привет Мир!");
    // Очистка ресурсов
    zh_160x_deinit(&lcd_handle);
}

Пример: Индикатор прогресса

#include "zh_160x_i2c.h"

#define I2C_PORT (I2C_NUM_MAX - 1)

zh_pcf8574_handle_t *lcd_expander = NULL;
zh_160x_i2c_handle_t *lcd_handle = NULL;

void app_main(void)
{
    // ... код инициализации ...
    for (uint8_t i = 0; i <= 100; ++i)
    {
        zh_160x_set_cursor(&lcd_handle, 0, 10);
        zh_160x_print_int(&lcd_handle, i);
        zh_160x_print_char(&lcd_handle, "%");
        zh_160x_print_progress_bar(&lcd_handle, 1, i);
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
    // Очистка ресурсов
    zh_160x_deinit(&lcd_handle);
}

Пример: Отображение различных типов данных

#include "zh_160x_i2c.h"

#define I2C_PORT (I2C_NUM_MAX - 1)

zh_pcf8574_handle_t *lcd_expander = NULL;
zh_160x_i2c_handle_t *lcd_handle = NULL;

void app_main(void)
{
    // ... код инициализации ...
    // Отображение строки
    zh_160x_set_cursor(&lcd_handle, 0, 0);
    zh_160x_print_char(&lcd_handle, "Строка: ");
    zh_160x_print_char(&lcd_handle, "Привет");
    // Отображение целого числа
    zh_160x_set_cursor(&lcd_handle, 1, 0);
    zh_160x_print_int(&lcd_handle, 42);
    // Отображение числа с плавающей точкой
    zh_160x_set_cursor(&lcd_handle, 0, 0);
    zh_160x_print_float(&lcd_handle, 3.14159, 2);  // 3.14
    // Включение курсора
    zh_160x_on_cursor(&lcd_handle, true);  // Мигающий курсор
    vTaskDelay(2000 / portTICK_PERIOD_MS);
    // Отключение курсора
    zh_160x_off_cursor(&lcd_handle);
    // Очистка ресурсов
    zh_160x_deinit(&lcd_handle);
}

Пример: Несколько LCD на одной шине

#include "zh_160x_i2c.h"

#define I2C_PORT (I2C_NUM_MAX - 1)

zh_pcf8574_handle_t *lcd1_expander = NULL;
zh_160x_i2c_handle_t *lcd1_handle = NULL;
zh_pcf8574_handle_t *lcd2_expander = NULL;
zh_160x_i2c_handle_t *lcd2_handle = NULL;

void app_main(void)
{
    esp_log_level_set("zh_160x_i2c", ESP_LOG_ERROR);
    esp_log_level_set("zh_pcf8574", ESP_LOG_ERROR);
    esp_log_level_set("zh_vector", ESP_LOG_ERROR);
    i2c_master_bus_config_t i2c_bus_config = {
        .clk_source = I2C_CLK_SRC_DEFAULT,
        .i2c_port = I2C_PORT,
        .scl_io_num = GPIO_NUM_22,
        .sda_io_num = GPIO_NUM_21,
        .glitch_ignore_cnt = 7,
        .flags.enable_internal_pullup = true,
    };
    i2c_master_bus_handle_t i2c_bus_handle = NULL;
    i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle);
    // Инициализация первого LCD по адресу 0x27
    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, &lcd1_expander);
    zh_160x_init(&lcd1_expander, &lcd1_handle, ZH_LCD_16X2);
    // Инициализация второго LCD по адресу 0x26
    config.i2c_address = 0x26;
    zh_pcf8574_init(&config, &lcd2_expander);
    zh_160x_init(&lcd2_expander, &lcd2_handle, ZH_LCD_16X2);
    // Отображение на первом LCD
    zh_160x_set_cursor(&lcd1_handle, 0, 0);
    zh_160x_print_char(&lcd1_handle, "LCD 1");
    // Отображение на втором LCD
    zh_160x_set_cursor(&lcd2_handle, 0, 0);
    zh_160x_print_char(&lcd2_handle, "LCD 2");
    // Очистка ресурсов
    zh_160x_deinit(&lcd1_handle);
    zh_160x_deinit(&lcd2_handle);
}

Технические характеристики

Параметр Значение
Типы LCD 1602A (16x2), 1604A (16x4)
Интерфейс I2C через PCF8574(A)
Диапазон адресов I2C 0x20-0x27 (PCF8574), 0x38-0x3F (PCF8574A)
Макс. LCD на шине 16
Использование GPIO 2 (SCL, SDA)
Версия ESP-IDF >= 5.0
Платформа Серия ESP32
Язык C (C99)

Коды ошибок

Код ошибки Описание
ESP_OK Операция выполнена успешно
ESP_ERR_INVALID_ARG Неверный аргумент (NULL указатель или неверное значение)
ESP_ERR_INVALID_STATE Дескриптор не инициализирован
ESP_FAIL Общий сбой (ошибка связи I2C)

Подключение

Подключение 1602A/1604A к PCF8574

Пин LCD Пин PCF8574 Описание
RS P0 Выбор регистра
E P2 Enable
D4 P4 Бит данных 4
D5 P5 Бит данных 5
D6 P6 Бит данных 6
D7 P7 Бит данных 7

Подключение I2C

LCD-модуль PCF8574 ESP32
VCC VCC 3.3V
GND GND GND
SDA SDA GPIO21
SCL SCL GPIO22
RW GND GND

Примечание: Пин RW должен быть подключен к GND для операции только записи.


Вклад в проект

Вклад приветствуется! Чтобы внести свой вклад:

  1. Сделайте форк репозитория
  2. Создайте ветку функции (git checkout -b feature/AmazingFeature)
  3. Закоммитьте ваши изменения (git commit -m 'Add some AmazingFeature')
  4. Отправьте в ветку (git push origin feature/AmazingFeature)
  5. Откройте Pull Request

Пожалуйста, убедитесь, что ваш код следует существующему стилю и включает соответствующую документацию.


Лицензия

Этот проект лицензирован по лицензии Apache, версия 2.0 - см. файл LICENSE для подробной информации.

Apache License, Version 2.0

Авторское право (c) 2026 Алексей Жолтиков

Лицензировано по лицензии Apache License, Version 2.0 (далее — "Лицензия"); вы не можете использовать этот файл, кроме случаев, предусмотренных Лицензией. Копию Лицензии можно получить по адресу:

http://www.apache.org/licenses/LICENSE-2.0

Если иное не требуется действующим законодательством или не согласовано в письменном виде, программное обеспечение, распространяемое по Лицензии, распространяется на условиях "КАК ЕСТЬ", БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, явных или подразумеваемых, включая, но не ограничиваясь, гарантии ТОВАРНОГО СОСТОЯНИЯ, ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ И НЕНАРУШЕНИЯ ПРАВ. Смотрите Лицензию для получения конкретных прав и ограничений.


Дополнительные заметки

  • Подтягивающие резисторы I2C: Используйте резисторы 4.7 кОм на линиях SDA и SCL для надежной связи
  • Питание: Обеспечьте стабильное питание 5 В для LCD-модуля (PCF8574 совместим с 5 В)
  • Настройка контраста: Используйте встроенный подстроечный резистор для настройки контраста LCD для оптимальной видимости
  • Подсветка: Подсветка LCD обычно подключается к VCC через резистор ограничения тока
  • Производительность: Операции блокирующие и используют задержки FreeRTOS для правильного тайминга
  • I2C_ISR_IRAM_SAFE: Для правильной работы включите I2C_ISR_IRAM_SAFE и I2C_MASTER_ISR_HANDLER_IN_IRAM в menuconfig
  • FreeRTOS: Для корректной работы настройте CONFIG_FREERTOS_HZ=1000 в menuconfig
  • Лучшие практики:
    • Всегда инициализируйте PCF8574 перед инициализацией LCD
    • Проверьте адрес I2C с помощью сканера, если LCD не отвечает
    • Учитывайте ограничения скорости шины I2C при использовании нескольких устройств

Generated for zh_160x_i2c v5.0.1