# display **Repository Path**: NetADs/display ## Basic Information - **Project Name**: display - **Description**: ESP-IDF架构。ESP32-S3-N16R8,TFT_LCD320x240SPI屏,ST7789V驱动。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-26 - **Last Updated**: 2026-07-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ESP-IDF ST7789 显示驱动组件 基于 ESP_LCD 标准架构的 ST7789 显示驱动组件,适配 ESP32 平台 TFT LCD 2.0 寸 240x320 彩色屏幕。 ## 特性 - ESP_LCD 标准架构:SPI 总线 + Panel IO + ST7789 Panel 三件套 - ST7789V 驱动,SPI 接口,RGB565 色深 - 内置 LEDC PWM 背光控制 (0-100%) - 显示旋转 (0/90/180/270) 和颜色反转 - 旋转后**自动交换有效分辨率**:`display_set_rotation()` 会同步更新 `display_get_width()/get_height()` 返回的逻辑分辨率(横屏 320x240),便于上层(如 LVGL)直接取用,无需本地维护横屏尺寸 - 兼容 ESP-IDF v5.x,可复用组件 ## 架构 ``` display.h (公共 API) │ src/display.c ├── spi_bus_initialize() SPI 总线初始化 ├── esp_lcd_new_panel_io_spi() Panel IO 句柄 ├── esp_lcd_new_panel_st7789() ST7789 Panel 句柄 ├── esp_lcd_panel_* ESP_LCD 标准面板操作 └── ledc_* PWM 背光控制 ``` ## 安装 ### 方式一:复制到 components 目录 ```bash cp -r display your_project/components/ ``` ### 方式二:Git 依赖 在 `main/idf_component.yml` 中添加: ```yaml dependencies: display: git: https://gitee.com/NetADs/display.git ``` ## 配置 运行 `idf.py menuconfig` → `Display Driver Configuration`: | 配置项 | 默认值 | 说明 | |--------|--------|------| | SPI SCK GPIO | 21 | 时钟引脚 | | SPI MOSI GPIO | 47 | 数据引脚 | | SPI CS GPIO | 41 | 片选引脚 | | DC GPIO | 40 | 数据/命令引脚 | | Reset GPIO | 45 | 复位引脚 | | Backlight GPIO | 42 | 背光引脚 | | Display Width | 240 | 宽度 (像素) | | Display Height | 320 | 高度 (像素) | | SPI Clock | 40 MHz | SPI 时钟频率 | | SPI Host | 2 | SPI 主机号 | | X Offset | 0 | 水平偏移 (像素) | | Y Offset | 0 | 垂直偏移 (像素) | ## API 参考 ### 初始化与反初始化 ```c esp_err_t display_init(const display_config_t *config); esp_err_t display_deinit(void); bool display_is_ready(void); ``` ### 显示控制 ```c esp_err_t display_set_backlight(uint8_t level); // 0-100 uint8_t display_get_backlight(void); esp_err_t display_set_rotation(display_rotation_t rotation); esp_err_t display_invert_colors(bool invert); esp_err_t display_sleep(void); esp_err_t display_wakeup(void); ``` ### 绘图 ```c esp_err_t display_draw_area(int x, int y, int w, int h, const void *data); esp_err_t display_fill_area(int x, int y, int w, int h, uint16_t color); esp_err_t display_set_pixel(int x, int y, uint16_t color); esp_err_t display_clear(uint16_t color); ``` ### 访问器 ```c esp_lcd_panel_handle_t display_get_panel(void); // LVGL 集成 esp_lcd_panel_io_handle_t display_get_io(void); // LVGL 集成 uint16_t display_get_width(void); uint16_t display_get_height(void); void *display_get_user_data(void); ``` ## 使用示例 ```c #include "display.h" void app_main(void) { display_config_t cfg = { .sck = 21, .mosi = 47, .cs = 41, .dc = 40, .rst = 45, .bl = 42, .bl_on_level = 1, .width = 240, .height = 320, .clk_hz = 40 * 1000 * 1000, .rotation = DISPLAY_ROTATION_0, .x_offset = 0, // 默认 0 .y_offset = 0, // 默认 0 }; ESP_ERROR_CHECK(display_init(&cfg)); ESP_ERROR_CHECK(display_clear(0x0000)); } ``` ## LVGL 集成 ### 竖屏 (240x320) ```c display_config_t cfg = { .width = 240, .height = 320, /* ... */ }; ESP_ERROR_CHECK(display_init(&cfg)); const lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG(); ESP_ERROR_CHECK(lvgl_port_init(&lvgl_cfg)); lvgl_port_display_cfg_t disp_cfg = { .io_handle = display_get_io(), .panel_handle = display_get_panel(), .hres = 240, .vres = 320, }; lv_disp_t *disp = lvgl_port_add_disp(&disp_cfg); lvgl_port_start(); ``` ### 横屏 (320x240) 驱动层以**物理分辨率**初始化 (240x320),通过 `display_set_rotation()` 旋转硬件**并自动交换有效分辨率**;之后 `display_get_width()/get_height()` 即返回 320/240,显示层可直接取用: ```c display_config_t cfg = { .width = 240, .height = 320, /* ... */ }; ESP_ERROR_CHECK(display_init(&cfg)); display_set_rotation(DISPLAY_ROTATION_90); // 必须在 attach 之前调用 // 旋转后 display_get_width()==320, display_get_height()==240 lvgl_port_display_cfg_t disp_cfg = { .io_handle = display_get_io(), .panel_handle = display_get_panel(), .hres = display_get_width(), .vres = display_get_height(), }; ``` > ⚠️ 配套 `lvgl_ui` 时,`draw_area` 回调契约是 `bool(true=成功)`,而 `display_draw_area()` 返回 `esp_err_t(ESP_OK==0)`,务必做 `== ESP_OK` 转换,否则成功时会被当成失败触发**双重 flush_ready**: > ```c > #include "esp_err.h" > static bool draw_area_wrapper(int x, int y, int w, int h, const void *data) { > return display_draw_area(x, y, w, h, data) == ESP_OK; > } > ``` > 色序:ST7789V 2.0" 屏多为 **BGR** 走线,建议 `CONFIG_DISPLAY_RGB_ELEMENT_ORDER_BGR=y`(见下方 Kconfig),否则红蓝互换。 ## 依赖 - `esp_lcd` (ESP-IDF) - `driver` (ESP-IDF) ## 许可证 MIT License