diff --git a/README.md b/README.md index 48e7e75..5e60903 100644 --- a/README.md +++ b/README.md @@ -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); + } +} +``` diff --git a/WIKI_EN.md b/WIKI_EN.md deleted file mode 100644 index aa577b2..0000000 --- a/WIKI_EN.md +++ /dev/null @@ -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* diff --git a/WIKI_RU.md b/WIKI_RU.md deleted file mode 100644 index 33e9289..0000000 --- a/WIKI_RU.md +++ /dev/null @@ -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*