diff --git a/wiki_ru.md b/wiki_ru.md new file mode 100644 index 0000000..4b6b35e --- /dev/null +++ b/wiki_ru.md @@ -0,0 +1,231 @@ +# Описание компонента 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` (сплошной блок), пустые — как пробелы. + +## Примеры использования + +### Базовый вывод текста + +```c +#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); +} +``` + +### Вывод числовых данных + +```c +// Вывод целого числа +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"); +``` + +### Отображение прогресс-бара + +```c +// Прогресс-бар требует настройки 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"`. + +```c +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 + +## Установка + +```bash +cd ваш_проект/components +git clone https://github.com/aZholtikov/zh_160x_i2c +``` + +```c +#include "zh_160x_i2c.h" +```