feat!: main structure of handle changed to double pointer

This commit is contained in:
aZholtikov committed 2026-08-25 19:57:53 +03:00
1 parent a37cab782c
commit 4abc0209b6
7 files changed
+646 -361

No files matched your search

+179 -82
View File
@@ -1,4 +1,4 @@
# zh_160x_i2c - Компонент ESP32 ESP-IDF для LCD 1602A/1604A через I2C (PCF8574)
# zh_160x_i2c - Компонент LCD 1602A/1604A через I2C (PCF8574) для ESP-IDF
## Содержание
@@ -25,39 +25,39 @@
## Возможности
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
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
---
## Установка
1. Перейдите в каталог компонентов вашего проекта:
Перейдите в каталог компонентов вашего проекта:
```bash
cd ../ваш_проект/components
```
2. Клонируйте репозиторий:
Клонируйте репозиторий:
```bash
git clone https://github.com/aZholtikov/zh_160x_i2c
```
3. В вашем приложении подключите заголовочный файл:
В вашем приложении подключите заголовочный файл:
```c
#include "zh_160x_i2c.h"
```
4. Компонент будет автоматически собран вместе с вашим проектом.
Компонент будет автоматически собран вместе с вашим проектом.
### Обязательные настройки в menuconfig
@@ -73,160 +73,223 @@ CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM
## Справочник API
### Константы конфигурации
### Типы данных
#### zh_160x_i2c_handle_t
```c
#define ZH_LCD_16X2 1 // Размер LCD 16x2
#define ZH_LCD_16X4 0 // Размер LCD 16x4
typedef struct _zh_160x_i2c_handle_t zh_160x_i2c_handle_t;
```
Непрозрачный дескриптор LCD-дисплея 160x I2C. Внутренняя структура, содержащая дескриптор расширителя PCF8574 и текущую конфигурацию размера LCD.
---
#### zh_160x_i2c_lcd_size_t
```c
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-дисплей 160x.
Выделяет и настраивает дескриптор LCD, затем отправляет последовательность инициализации на контроллер LCD через расширитель I2C PCF8574. Настраивает 4-битный режим и устанавливает параметры дисплея по умолчанию.
**Параметры:**
- `handle` - Указатель на уникальный дескриптор PCF8574 (должен быть уже инициализирован)
- `expander` - Указатель на дескриптор расширителя PCF8574. Не должен быть NULL
- `handle` - Выходной указатель для нового выделенного дескриптора LCD. Должен быть NULL
- `size` - Размер LCD (ZH_LCD_16X2 или ZH_LCD_16X4)
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle или handle не инициализирован)
- `ESP_FAIL` - Ошибка инициализации
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL указатель или неверный размер)
- `ESP_ERR_INVALID_STATE` - Дескриптор уже инициализирован
- `ESP_ERR_NO_MEM` - Ошибка выделения памяти
- `ESP_FAIL` - Сбой последовательности инициализации LCD
**Пример:**
```c
zh_pcf8574_handle_t lcd_handle = {0};
// Сначала инициализируйте PCF8574
zh_pcf8574_init(&config, &lcd_handle);
// Затем инициализируйте LCD
zh_160x_init(&lcd_handle, ZH_LCD_16X2);
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 и перемещает курсор в домашнюю позицию.
Отправляет команду очистки LCD (0x01) для стирания всего отображаемого текста и сброса курсора в верхний левый угол (строка 0, столбец 0).
**Параметры:**
- `handle` - Указатель на уникальный дескриптор PCF8574
- `handle` - Указатель на дескриптор LCD. Не должен быть NULL
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle)
- `ESP_FAIL` - Операция не удалась
- `ESP_FAIL` - Ошибка отправки команды
---
### zh_160x_set_cursor()
Устанавливает курсор в определенную позицию на LCD.
Устанавливает курсор в указанную позицию на LCD.
Перемещает курсор в указанную строку и столбец.
Для дисплеев 16x2: строки 0–1, столбцы 0–15.
Для дисплеев 16x4: строки 0–3, столбцы 0–15.
**Параметры:**
- `handle` - Указатель на уникальный дескриптор PCF8574
- `row` - Номер строки (0-1 для 16x2, 0-3 для 16x4)
- `col` - Номер столбца (0-15)
- `handle` - Указатель на дескриптор LCD. Не должен быть NULL
- `row` - Номер строки (0–1 для 16x2, 0–3 для 16x4)
- `col` - Номер столбца (0–15)
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle, неверный row/col)
- `ESP_FAIL` - Операция не удалась
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle или координаты вне диапазона)
- `ESP_FAIL` - Ошибка отправки команды
**Примечание:**
Адресация строк: строка 0 = 0x00, строка 1 = 0x40, строка 2 = 0x10, строка 3 = 0x50.
---
### zh_160x_print_char()
Выводит строку на LCD.
Выводит строку на LCD в текущую позицию курсора.
Передаёт каждый символ строки, завершающейся нулём, на LCD в 4-битном режиме. Курсор автоматически перемещается после каждого символа.
**Параметры:**
- `handle` - Указатель на уникальный дескриптор PCF8574
- `str` - Указатель на null-terminated строку для отображения
- `handle` - Указатель на дескриптор LCD. Не должен быть NULL
- `str` - Указатель на null-terminated строку для отображения. Не должен быть NULL
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle или str)
- `ESP_FAIL` - Операция не удалась
- `ESP_FAIL` - Ошибка передачи символа
---
### zh_160x_print_int()
Выводит целое число на LCD.
Выводит целое число на LCD в текущую позицию курсора.
Преобразует целое число в десятичную строку и отображает её.
Поддерживает отрицательные числа (максимум 11 цифр плюс знак).
**Параметры:**
- `handle` - Указатель на уникальный дескриптор PCF8574
- `handle` - Указатель на дескриптор LCD. Не должен быть NULL
- `num` - Целочисленное значение для отображения
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle)
- `ESP_FAIL` - Операция не удалась
- `ESP_FAIL` - Ошибка преобразования строки или печати
---
### zh_160x_print_float()
Выводит число с плавающей точкой на LCD.
Выводит число с плавающей точкой на LCD в текущую позицию курсора.
Преобразует значение с плавающей точкой в строку с указанной точностью десятичных знаков и отображает её.
**Параметры:**
- `handle` - Указатель на уникальный дескриптор PCF8574
- `handle` - Указатель на дескриптор LCD. Не должен быть NULL
- `num` - Значение с плавающей точкой для отображения
- `precision` - Количество знаков после запятой (0-9)
- `precision` - Количество знаков после запятой (0–6 рекомендуется)
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle)
- `ESP_FAIL` - Операция не удалась
- `ESP_FAIL` - Ошибка преобразования строки или печати
---
### zh_160x_print_progress_bar()
Отображает индикатор прогресса в определенной строке LCD.
Отображает индикатор прогресса в указанной строке LCD.
Отрисовывает 16-блочный индикатор прогресса с использованием пользовательского символа (0xFF).
Заполненные блоки представляют процент прогресса, пустые блоки показывают остаток.
**Параметры:**
- `handle` - Указатель на уникальный дескриптор PCF8574
- `row` - Номер строки (0-1 для 16x2, 0-3 для 16x4)
- `progress` - Процент прогресса (0-100)
- `handle` - Указатель на дескриптор LCD. Не должен быть NULL
- `row` - Номер строки (0–1 для 16x2, 0–3 для 16x4)
- `progress` - Процент прогресса (0–100)
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle, неверный row или progress)
- `ESP_FAIL` - Операция не удалась
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle, row вне диапазона или progress > 100)
- `ESP_FAIL` - Ошибка установки курсора или печати символов
---
### zh_160x_clear_row()
Очищает определенную строку на LCD.
Очищает указанную строку на LCD.
Перемещает курсор в начало указанной строки и заполняет все 16 позиций пробелами для стирания содержимого.
Курсор остаётся в начале очищенной строки.
**Параметры:**
- `handle` - Указатель на уникальный дескриптор PCF8574
- `row` - Номер строки (0-1 для 16x2, 0-3 для 16x4)
- `handle` - Указатель на дескриптор LCD. Не должен быть NULL
- `row` - Номер строки (0–1 для 16x2, 0–3 для 16x4)
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle, неверный row)
- `ESP_FAIL` - Операция не удалась
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle или row вне диапазона)
- `ESP_FAIL` - Ошибка установки курсора или печати символов
---
@@ -234,32 +297,37 @@ zh_160x_init(&lcd_handle, ZH_LCD_16X2);
Включает курсор с опциональным режимом мигания.
Включает курсор и при необходимости активирует мигание.
Команда 0x0F включает курсор с миганием, 0x0E включает курсор без мигания.
**Параметры:**
- `handle` - Указатель на уникальный дескриптор PCF8574
- `blink` - Если true, курсор мигает; если false, курсор статичный
- `handle` - Указатель на дескриптор LCD. Не должен быть NULL
- `blink` - Если true, включается мигающий курсор; если false — статичный курсор
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle)
- `ESP_FAIL` - Операция не удалась
- `ESP_FAIL` - Ошибка отправки команды
---
### zh_160x_off_cursor()
Отключает курсор.
Отключает курсор и отключает мигание.
Отправляет команду 0x0C для отключения курсора и мигания курсора.
**Параметры:**
- `handle` - Указатель на уникальный дескриптор PCF8574
- `handle` - Указатель на дескриптор LCD. Не должен быть NULL
**Возвращает:**
- `ESP_OK` - Успех
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle)
- `ESP_FAIL` - Операция не удалась
- `ESP_FAIL` - Ошибка отправки команды
---
@@ -272,7 +340,8 @@ zh_160x_init(&lcd_handle, ZH_LCD_16X2);
#define I2C_PORT (I2C_NUM_MAX - 1)
zh_pcf8574_handle_t lcd_160x_handle = {0};
zh_pcf8574_handle_t *lcd_expander = NULL;
zh_160x_i2c_handle_t *lcd_handle = NULL;
void app_main(void)
{
@@ -287,19 +356,26 @@ void app_main(void)
.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;
zh_pcf8574_init(&config, &lcd_160x_handle);
zh_160x_init(&lcd_160x_handle, ZH_LCD_16X2);
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_160x_handle, 0, 0);
zh_160x_print_char(&lcd_160x_handle, "LCD 160X");
zh_160x_set_cursor(&lcd_160x_handle, 1, 0);
zh_160x_print_char(&lcd_160x_handle, "Привет Мир!");
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);
}
```
@@ -308,9 +384,13 @@ void app_main(void)
```c
#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_pcf8574_handle_t lcd_handle = {0};
// ... код инициализации ...
for (uint8_t i = 0; i <= 100; ++i)
{
@@ -320,6 +400,8 @@ void app_main(void)
zh_160x_print_progress_bar(&lcd_handle, 1, i);
vTaskDelay(100 / portTICK_PERIOD_MS);
}
// Очистка ресурсов
zh_160x_deinit(&lcd_handle);
}
```
@@ -328,9 +410,13 @@ void app_main(void)
```c
#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_pcf8574_handle_t lcd_handle = {0};
// ... код инициализации ...
// Отображение строки
zh_160x_set_cursor(&lcd_handle, 0, 0);
@@ -347,6 +433,8 @@ void app_main(void)
vTaskDelay(2000 / portTICK_PERIOD_MS);
// Отключение курсора
zh_160x_off_cursor(&lcd_handle);
// Очистка ресурсов
zh_160x_deinit(&lcd_handle);
}
```
@@ -357,8 +445,10 @@ void app_main(void)
#define I2C_PORT (I2C_NUM_MAX - 1)
zh_pcf8574_handle_t lcd1_handle = {0};
zh_pcf8574_handle_t lcd2_handle = {0};
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)
{
@@ -379,18 +469,21 @@ void app_main(void)
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_handle);
zh_160x_init(&lcd1_handle, ZH_LCD_16X2);
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_handle);
zh_160x_init(&lcd2_handle, ZH_LCD_16X2);
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);
}
```
@@ -399,14 +492,14 @@ void app_main(void)
## Технические характеристики
| Параметр | Значение |
|----------|----------|
| ---------- | ---------- |
| **Типы 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 |
| **Платформа** | Серия ESP32 |
| **Язык** | C (C99) |
---
@@ -414,7 +507,7 @@ void app_main(void)
## Коды ошибок
| Код ошибки | Описание |
|------------|----------|
| ------------ | ---------- |
| `ESP_OK` | Операция выполнена успешно |
| `ESP_ERR_INVALID_ARG` | Неверный аргумент (NULL указатель или неверное значение) |
| `ESP_ERR_INVALID_STATE` | Дескриптор не инициализирован |
@@ -498,3 +591,7 @@ void app_main(void)
- Всегда инициализируйте PCF8574 перед инициализацией LCD
- Проверьте адрес I2C с помощью сканера, если LCD не отвечает
- Учитывайте ограничения скорости шины I2C при использовании нескольких устройств
---
*Generated for zh_160x_i2c v5.0.0*