doc: updated readme

This commit is contained in:
aZholtikov committed 2026-08-30 17:17:42 +03:00
1 parent facf8b802b
commit 50f2062e46
3 files changed
+65 -1205

No files matched your search

+65 -11
View File
@@ -1,13 +1,5 @@
# ESP32 ESP-IDF component for LCD 1602A/1604A via I2C (PCF8574)
## Wiki
[EN](WIKI_EN.md) | [RU](WIKI_RU.md)
## Tested on
1. [ESP32 ESP-IDF v6.0.0](https://docs.espressif.com/projects/esp-idf/en/v6.0/esp32/index.html)
## SAST Tools
[PVS-Studio](https://pvs-studio.com/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) — static analyzer for C, C++, C#, and Java code.
@@ -21,11 +13,21 @@
5. Cursor visibility and blink control.
6. Row-specific clear operations.
## Note
Enable the following settings in menuconfig:
```text
CONFIG_FREERTOS_HZ=1000
CONFIG_I2C_ISR_IRAM_SAFE
CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM
```
## Using
In an existing project, run the following command to install the component:
```text
```bash
cd ../your_project/components
git clone https://github.com/aZholtikov/zh_160x_i2c
```
@@ -36,6 +38,58 @@ In the application, add the component:
#include "zh_160x_i2c.h"
```
## Examples
## Example
See Wiki [EN](WIKI_EN.md#usage-examples) | [RU](WIKI_RU.md#примеры-использования)
```c
#include "zh_160x_i2c.h"
#define I2C_PORT (I2C_NUM_MAX - 1)
zh_pcf8574_handle_t *pcf8574_handle = NULL;
zh_160x_i2c_handle_t *lcd_160x_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;
zh_pcf8574_init(&config, &pcf8574_handle);
zh_160x_init(&pcf8574_handle, &lcd_160x_handle, ZH_LCD_16X2);
for (;;)
{
zh_160x_on_cursor(&lcd_160x_handle, true);
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, "Hello World!");
vTaskDelay(5000 / portTICK_PERIOD_MS);
zh_160x_off_cursor(&lcd_160x_handle);
zh_160x_set_cursor(&lcd_160x_handle, 0, 0);
zh_160x_print_char(&lcd_160x_handle, "Progress: ");
for (uint8_t i = 0; i <= 100; ++i)
{
zh_160x_set_cursor(&lcd_160x_handle, 0, 10);
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(100 / portTICK_PERIOD_MS);
}
vTaskDelay(5000 / portTICK_PERIOD_MS);
zh_160x_lcd_clear(&lcd_160x_handle);
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
```
-597
View File
@@ -1,597 +0,0 @@
# zh_160x_i2c - LCD 1602A/1604A via I2C (PCF8574) Component for ESP-IDF
## Table of Contents
- [Overview](#overview)
- [Features](#features)
- [Installation](#installation)
- [API Reference](#api-reference)
- [Usage Examples](#usage-examples)
- [Technical Specifications](#technical-specifications)
- [Error Codes](#error-codes)
- [Connection](#connection)
- [Contributing](#contributing)
- [License](#license)
---
## Overview
`zh_160x_i2c` is a lightweight ESP-IDF component for controlling LCD 1602A and 1604A displays via I2C interface using PCF8574(A) I/O expanders. This component simplifies the process of displaying text, numbers, and progress bars on character LCD modules by providing a simple and intuitive API.
The component is designed specifically for ESP32 microcontrollers and uses ESP-IDF's I2C master driver and FreeRTOS for optimal performance in embedded systems.
---
## Features
1. **[Simple API]**: Easy-to-use functions for common LCD operations
2. **[I2C Interface]**: Uses only 2 GPIO pins (SCL and SDA) via PCF8574 expander
3. **[Support for 1602A and 1604A]**: Supports both 16x2 and 16x4 LCD modules
4. **[Multiple LCD Support]**: Up to 16 LCD modules on one I2C bus
5. **[Text Display]**: Print strings, integers, and floating-point numbers
6. **[Cursor Control]**: Enable/disable cursor with optional blink
7. **[Progress Bar]**: Display progress bars on LCD
8. **[Row Operations]**: Clear specific rows
9. **[ESP-IDF Optimized]**: Uses ESP-IDF's I2C master driver and FreeRTOS
---
## Installation
Navigate to your project's components directory:
```bash
cd ../your_project/components
```
Clone the repository:
```bash
git clone https://github.com/aZholtikov/zh_160x_i2c
```
In your application, include the header:
```c
#include "zh_160x_i2c.h"
```
The component will be automatically built with your project.
### Required menuconfig Settings
For correct operation, enable the following settings in menuconfig:
```text
CONFIG_FREERTOS_HZ=1000
CONFIG_I2C_ISR_IRAM_SAFE
CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM
```
---
## API Reference
### Data Types
#### zh_160x_i2c_handle_t
```c
typedef struct _zh_160x_i2c_handle_t zh_160x_i2c_handle_t;
```
Opaque handle for LCD 160x I2C display. Internal structure containing the PCF8574 expander handle and the current LCD size configuration.
---
#### zh_160x_i2c_lcd_size_t
```c
typedef enum
{
ZH_LCD_16X2 = 0, /*!< LCD size 16x2 */
ZH_LCD_16X4, /*!< LCD size 16x4 */
ZH_LCD_NUM_MAX
} zh_160x_i2c_lcd_size_t;
```
Enumeration of supported LCD display sizes.
| Value | Description |
|-------|-------------|
| `ZH_LCD_16X2` | LCD size 16x2 (2 rows of 16 characters) |
| `ZH_LCD_16X4` | LCD size 16x4 (4 rows of 16 characters) |
---
### zh_160x_init()
Initializes the LCD 160x display.
Allocates and configures the LCD handle, then sends the initialization sequence to the LCD controller via the PCF8574 I2C expander. Configures 4-bit mode and sets default display parameters.
**Parameters:**
- `expander` - Pointer to the PCF8574 expander handle. Must not be NULL
- `handle` - Output pointer for the newly allocated LCD handle. Must be NULL
- `size` - LCD size (ZH_LCD_16X2 or ZH_LCD_16X4)
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL pointer or invalid size)
- `ESP_ERR_INVALID_STATE` - Handle already initialized
- `ESP_ERR_NO_MEM` - Memory allocation failure
- `ESP_FAIL` - LCD initialization sequence failure
**Example:**
```c
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) {
// Error handling
}
err = zh_160x_init(&lcd_expander, &lcd_handle, ZH_LCD_16X2);
if (err != ESP_OK) {
// Error handling
}
```
**Note:**
The PCF8574 expander must be initialized before initializing the LCD.
---
### zh_160x_lcd_clear()
Clears the LCD screen and moves the cursor to the home position.
Sends the LCD clear command (0x01) to erase all displayed text and reset the cursor to the upper-left corner (row 0, column 0).
**Parameters:**
- `handle` - Pointer to the LCD handle. Must not be NULL
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle)
- `ESP_FAIL` - Command send failure
---
### zh_160x_set_cursor()
Sets the cursor to a specific position on the LCD.
Moves the cursor to the specified row and column.
For 16x2 displays: rows 0–1, columns 0–15.
For 16x4 displays: rows 0–3, columns 0–15.
**Parameters:**
- `handle` - Pointer to the LCD handle. Must not be NULL
- `row` - Row number (0–1 for 16x2, 0–3 for 16x4)
- `col` - Column number (0–15)
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle or coordinates out of range)
- `ESP_FAIL` - Command send failure
**Note:**
Row address mapping: row 0 = 0x00, row 1 = 0x40, row 2 = 0x10, row 3 = 0x50.
---
### zh_160x_print_char()
Prints a string to the LCD at the current cursor position.
Transmits each character of the null-terminated string to the LCD in 4-bit mode. The cursor advances automatically after each character.
**Parameters:**
- `handle` - Pointer to the LCD handle. Must not be NULL
- `str` - Pointer to the null-terminated string to display. Must not be NULL
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle or str)
- `ESP_FAIL` - Character transmission failure
---
### zh_160x_print_int()
Prints an integer to the LCD at the current cursor position.
Converts the integer to a decimal string and displays it.
Supports negative numbers (maximum 11 digits plus sign).
**Parameters:**
- `handle` - Pointer to the LCD handle. Must not be NULL
- `num` - Integer value to display
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle)
- `ESP_FAIL` - String conversion or print failure
---
### zh_160x_print_float()
Prints a floating-point number to the LCD at the current cursor position.
Converts the floating-point value to a string with the specified decimal precision and displays it.
**Parameters:**
- `handle` - Pointer to the LCD handle. Must not be NULL
- `num` - Floating-point value to display
- `precision` - Number of decimal places (0–6 recommended)
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle)
- `ESP_FAIL` - String conversion or print failure
---
### zh_160x_print_progress_bar()
Displays a progress bar on a specific row of the LCD.
Renders a 16-block progress bar using a custom character (0xFF).
Filled blocks represent the progress percentage, empty blocks show the remainder.
**Parameters:**
- `handle` - Pointer to the LCD handle. Must not be NULL
- `row` - Row number (0–1 for 16x2, 0–3 for 16x4)
- `progress` - Progress percentage (0–100)
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle, row out of range, or progress > 100)
- `ESP_FAIL` - Cursor positioning or character print failure
---
### zh_160x_clear_row()
Clears a specific row on the LCD.
Moves the cursor to the beginning of the specified row and fills all 16 positions with spaces to erase existing content.
The cursor remains at the start of the cleared row.
**Parameters:**
- `handle` - Pointer to the LCD handle. Must not be NULL
- `row` - Row number (0–1 for 16x2, 0–3 for 16x4)
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle or row out of range)
- `ESP_FAIL` - Cursor positioning or character print failure
---
### zh_160x_on_cursor()
Enables the cursor with optional blink mode.
Turns on the cursor and optionally enables blinking.
Command 0x0F enables cursor with blink, 0x0E enables cursor only.
**Parameters:**
- `handle` - Pointer to the LCD handle. Must not be NULL
- `blink` - If true, enables blinking cursor; if false, solid cursor
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle)
- `ESP_FAIL` - Command send failure
---
### zh_160x_off_cursor()
Hides the cursor and disables blinking.
Sends command 0x0C to turn off both cursor and cursor blink.
**Parameters:**
- `handle` - Pointer to the LCD handle (not NULL)
**Returns:**
- `ESP_OK` - Success
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle)
- `ESP_FAIL` - Command send failure
---
## Usage Examples
### Basic Example: Single LCD Display
```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)
{
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;
}
// Display text
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, "Hello World!");
// Cleanup
zh_160x_deinit(&lcd_handle);
}
```
### Example: Progress Bar
```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)
{
// ... initialization code ...
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);
}
// Cleanup
zh_160x_deinit(&lcd_handle);
}
```
### Example: Displaying Various Data Types
```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)
{
// ... initialization code ...
// Display string
zh_160x_set_cursor(&lcd_handle, 0, 0);
zh_160x_print_char(&lcd_handle, "String: ");
zh_160x_print_char(&lcd_handle, "Hello");
// Display integer
zh_160x_set_cursor(&lcd_handle, 1, 0);
zh_160x_print_int(&lcd_handle, 42);
// Display floating-point number
zh_160x_set_cursor(&lcd_handle, 0, 0);
zh_160x_print_float(&lcd_handle, 3.14159, 2); // 3.14
// Enable cursor
zh_160x_on_cursor(&lcd_handle, true); // Blinking cursor
vTaskDelay(2000 / portTICK_PERIOD_MS);
// Disable cursor
zh_160x_off_cursor(&lcd_handle);
// Cleanup
zh_160x_deinit(&lcd_handle);
}
```
### Example: Multiple LCDs on One Bus
```c
#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);
// Initialize first LCD at address 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);
// Initialize second LCD at address 0x26
config.i2c_address = 0x26;
zh_pcf8574_init(&config, &lcd2_expander);
zh_160x_init(&lcd2_expander, &lcd2_handle, ZH_LCD_16X2);
// Display on first LCD
zh_160x_set_cursor(&lcd1_handle, 0, 0);
zh_160x_print_char(&lcd1_handle, "LCD 1");
// Display on second LCD
zh_160x_set_cursor(&lcd2_handle, 0, 0);
zh_160x_print_char(&lcd2_handle, "LCD 2");
// Cleanup
zh_160x_deinit(&lcd1_handle);
zh_160x_deinit(&lcd2_handle);
}
```
---
## Technical Specifications
| Parameter | Value |
| ----------- | ------- |
| **LCD Types** | 1602A (16x2), 1604A (16x4) |
| **Interface** | I2C via PCF8574(A) |
| **I2C Address Range** | 0x20-0x27 (PCF8574), 0x38-0x3F (PCF8574A) |
| **Max LCDs per Bus** | 16 |
| **GPIO Usage** | 2 (SCL, SDA) |
| **ESP-IDF Version** | >= 5.0 |
| **Platform** | ESP32 series |
| **Language** | C (C99) |
---
## Error Codes
| Error Code | Description |
| ------------ | ------------- |
| `ESP_OK` | Operation completed successfully |
| `ESP_ERR_INVALID_ARG` | Invalid argument (NULL pointer or invalid value) |
| `ESP_ERR_INVALID_STATE` | Handle not initialized |
| `ESP_FAIL` | General failure (I2C communication error) |
---
## Connection
### 1602A/1604A to PCF8574 Connection
| LCD Pin | PCF8574 Pin | Description |
|---------|-------------|-------------|
| RS | P0 | Register select |
| E | P2 | Enable |
| D4 | P4 | Data bit 4 |
| D5 | P5 | Data bit 5 |
| D6 | P6 | Data bit 6 |
| D7 | P7 | Data bit 7 |
### I2C Connection
| LCD Module | PCF8574 | ESP32 |
|------------|---------|-------|
| VCC | VCC | 3.3V |
| GND | GND | GND |
| SDA | SDA | GPIO21 |
| SCL | SCL | GPIO22 |
| RW | GND | GND |
**Note:** RW pin must be connected to GND for write-only operation.
---
## Contributing
Contributions are welcome! To contribute:
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request
Please ensure your code follows the existing style and includes appropriate documentation.
---
## License
This project is licensed under the Apache License, Version 2.0 - see the [LICENSE](LICENSE) file for details.
### Apache License, Version 2.0
Copyright (c) 2026 Alexey Zholtikov
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---
## Additional Notes
- **I2C Pull-up Resistors**: Use 4.7kΩ resistors on SDA and SCL lines for reliable communication
- **Power Supply**: Ensure stable 5V power for LCD module (PCF8574 is 5V tolerant)
- **Contrast Adjustment**: Use the built-in potentiometer to adjust LCD contrast for optimal visibility
- **Backlight**: LCD backlight is typically connected to VCC through a current-limiting resistor
- **Performance**: Operations are blocking and use FreeRTOS delays for proper timing
- **I2C_ISR_IRAM_SAFE**: For proper operation, enable `I2C_ISR_IRAM_SAFE` and `I2C_MASTER_ISR_HANDLER_IN_IRAM` in menuconfig
- **FreeRTOS**: For correct operation, configure `CONFIG_FREERTOS_HZ=1000` in menuconfig
- **Best Practices**:
- Always initialize PCF8574 before initializing LCD
- Check I2C address using a scanner if LCD does not respond
- Consider I2C bus speed limitations when using multiple devices
---
*Generated for zh_160x_i2c v5.0.1*
-597
View File
@@ -1,597 +0,0 @@
# zh_160x_i2c - Компонент LCD 1602A/1604A через I2C (PCF8574) для ESP-IDF
## Содержание
- [Обзор](#обзор)
- [Возможности](#возможности)
- [Установка](#установка)
- [Справочник API](#справочник-api)
- [Примеры использования](#примеры-использования)
- [Технические характеристики](#технические-характеристики)
- [Коды ошибок](#коды-ошибок)
- [Подключение](#подключение)
- [Вклад в проект](#вклад-в-проект)
- [Лицензия](#лицензия)
---
## Обзор
`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
---
## Установка
Перейдите в каталог компонентов вашего проекта:
```bash
cd ../ваш_проект/components
```
Клонируйте репозиторий:
```bash
git clone https://github.com/aZholtikov/zh_160x_i2c
```
В вашем приложении подключите заголовочный файл:
```c
#include "zh_160x_i2c.h"
```
Компонент будет автоматически собран вместе с вашим проектом.
### Обязательные настройки в menuconfig
Для корректной работы компонента включите следующие настройки в menuconfig:
```text
CONFIG_FREERTOS_HZ=1000
CONFIG_I2C_ISR_IRAM_SAFE
CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM
```
---
## Справочник API
### Типы данных
#### zh_160x_i2c_handle_t
```c
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, затем отправляет последовательность инициализации на контроллер 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
**Пример:**
```c
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-дисплей
```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)
{
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);
}
```
### Пример: Индикатор прогресса
```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)
{
// ... код инициализации ...
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);
}
```
### Пример: Отображение различных типов данных
```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_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 на одной шине
```c
#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](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*