doc: updated readme
This commit is contained in:
1 parent
facf8b802b
commit
50f2062e46
3 files changed
+65
-1205
No files matched your search
@@ -1,13 +1,5 @@
|
|||||||
# ESP32 ESP-IDF component for LCD 1602A/1604A via I2C (PCF8574)
|
# 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
|
## 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.
|
[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.
|
5. Cursor visibility and blink control.
|
||||||
6. Row-specific clear operations.
|
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
|
## Using
|
||||||
|
|
||||||
In an existing project, run the following command to install the component:
|
In an existing project, run the following command to install the component:
|
||||||
|
|
||||||
```text
|
```bash
|
||||||
cd ../your_project/components
|
cd ../your_project/components
|
||||||
git clone https://github.com/aZholtikov/zh_160x_i2c
|
git clone https://github.com/aZholtikov/zh_160x_i2c
|
||||||
```
|
```
|
||||||
@@ -36,6 +38,58 @@ In the application, add the component:
|
|||||||
#include "zh_160x_i2c.h"
|
#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
@@ -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
@@ -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*
|
|
||||||
Reference in new issue
Block a user