Dzbj_ESP32-S3/项目对比分析报告.md

10 KiB
Raw Blame History

项目对比分析报告

1. 项目概述

本次分析对比了两个基于 ESP32 平台的 LCD 驱动项目,重点分析 d zbj 项目在适配 LVGL 时遇到的问题:

项目名称 路径 主要功能
d zbj 项目 /Users/rdzleo/Desktop/dzbj 完整的嵌入式应用,包含 LCD 显示、触摸等功能
QSPI LCD 驱动版本 /Users/rdzleo/Desktop/qspi_lcd_驱动版本 专注于 LCD 驱动和触摸功能的实现LVGL 适配成功

2. 项目结构对比

2.1 d zbj 项目结构

dzbj/
├── main/
│   ├── axis/        # 轴控制相关代码
│   ├── ble/         # BLE 蓝牙功能
│   ├── fatfs/       # 文件系统功能
│   ├── gpio/        # GPIO 控制
│   ├── lcd/         # LCD 驱动实现
│   ├── pages/       # 页面管理
│   ├── temp/        # 温度检测
│   ├── ui/          # UI 界面SquareLine Studio 生成)
│   ├── wifi/        # WiFi 功能
│   └── main.c       # 主函数
├── build/           # 构建输出
└── CMakeLists.txt   # 构建配置

2.2 QSPI LCD 驱动版本结构

qspi_lcd_驱动版本/
├── main/
│   ├── display_touch_manager.h  # 显示和触摸管理接口
│   ├── lcd_touch_driver.h       # LCD 触摸驱动接口
│   └── main.c                   # 主函数
├── components/
│   └── lvgl/                    # LVGL 组件
└── CMakeLists.txt               # 构建配置

3. LCD 驱动实现对比

3.1 d zbj 项目 LCD 实现

核心文件/Users/rdzleo/Desktop/dzbj/main/lcd/lcd.c

实现特点

  • 使用 QSPI 接口驱动 ST77916 LCD 控制器
  • 直接调用 ESP-IDF 提供的 LCD 相关 API
  • 分步骤初始化SPI 总线 → LCD IO → LCD 面板 → 重置和初始化面板
  • 支持触摸功能CST816S 触摸控制器)
  • 配置了双缓冲和 DMA 传输

关键代码

void lcd_init(){
    const spi_bus_config_t buscfg = ST77916_PANEL_BUS_QSPI_CONFIG(...);
    spi_bus_initialize(SPI_LCD_HOST, &buscfg, SPI_DMA_CH_AUTO);
    const esp_lcd_panel_io_spi_config_t io_config = ST77916_PANEL_IO_QSPI_CONFIG(...);
    ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(...));
    const st77916_vendor_config_t vendor_config = {
        .flags = {
            .use_qspi_interface = 1,
        },
    };
    const esp_lcd_panel_dev_config_t panel_config = {...};
    ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(...));
    esp_lcd_panel_reset(panel_handle);
    esp_lcd_panel_init(panel_handle);
    esp_lcd_panel_disp_on_off(panel_handle, true);
}

3.2 QSPI LCD 驱动版本实现

核心文件:通过 display_manager_init() 函数实现

实现特点

  • 使用显示管理器和触摸管理器的抽象层
  • 封装了 LCD 初始化的细节
  • 提供统一的接口函数
  • 结构更清晰,职责更明确

关键代码

void app_main(void) {
    // 初始化显示管理器
    esp_err_t ret = display_manager_init();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "显示管理器初始化失败: %s", esp_err_to_name(ret));
        return;
    }

    // 获取显示驱动
    lv_disp_t *display = display_manager_get_display();
    if (display == NULL) {
        ESP_LOGE(TAG, "获取显示驱动失败");
        return;
    }

    // 初始化触摸管理器
    ret = touch_manager_init(display);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "触摸管理器初始化失败: %s", esp_err_to_name(ret));
        return;
    }
}

3.3 驱动实现对比分析

对比项 d zbj 项目 QSPI LCD 驱动版本
接口方式 直接调用 ESP-IDF API 使用抽象层管理器
代码复杂度 相对复杂,包含更多细节 更简洁,封装了细节
可维护性 模块化但分散 集中管理,更易维护
灵活性 高度灵活,可自定义各环节 标准化流程,灵活性稍低
初始化流程 线性初始化各组件 分层初始化,结构更清晰
错误处理 基本错误检查 详细的错误处理和日志

4. 初始化流程对比

4.1 d zbj 项目初始化流程

核心文件/Users/rdzleo/Desktop/dzbj/main/main.c

初始化顺序

  1. i2c_init() - 初始化 I2C 总线
  2. nvs_init() - 初始化 NVS 存储
  3. lcd_init() - 初始化 LCD 面板
  4. touch_init() - 初始化触摸控制器
  5. lvgl_lcd_init() - 初始化 LVGL 显示
  6. fatfs_init() - 初始化文件系统
  7. pwm_init() - 初始化 PWM 背光
  8. app_test_display() - 显示测试屏幕

4.2 QSPI LCD 驱动版本初始化流程

核心文件/Users/rdzleo/Desktop/qspi_lcd_驱动版本/main/main.c

初始化顺序

  1. display_manager_init() - 初始化显示管理器
  2. display_manager_get_display() - 获取显示驱动
  3. 创建 LVGL 任务
  4. 等待 LVGL 任务启动
  5. ui_init() - 初始化 SquareLine Studio UI
  6. 等待 LVGL 完成初始渲染
  7. touch_manager_init(display) - 初始化触摸管理器
  8. 控制 LCD 开关状态

5. 技术选型对比

5.1 硬件平台

  • d zbj 项目ESP32-S3 系列
  • QSPI LCD 驱动版本ESP32-S3 系列

5.2 LCD 控制器

  • d zbj 项目ST77916S
  • QSPI LCD 驱动版本ST77916S

7.3 通信接口

  • d zbj 项目QSPILCD、I2C触摸
  • QSPI LCD 驱动版本QSPILCD、I2C触摸

7.4 软件框架

  • d zbj 项目ESP-IDF + LVGL + SquareLine Studio
  • QSPI LCD 驱动版本ESP-IDF + LVGL + SquareLine Studio

7.5 SDK 配置对比

配置项 d zbj 项目 QSPI LCD 驱动版本
ESP-IDF 版本 5.4.2 最新稳定版
编译器 xtensa-esp32s3-elf-gcc xtensa-esp32s3-elf-gcc
构建系统 CMake CMake
目标芯片 esp32s3 esp32s3

7.6 LVGL 配置对比

配置项 d zbj 项目 QSPI LCD 驱动版本
LVGL 版本 8.3.11 8.3.11
颜色深度 16位 (CONFIG_LV_COLOR_DEPTH_16=y) 16位 (CONFIG_LV_COLOR_DEPTH_16=y)
字节交换 启用 (CONFIG_LV_COLOR_16_SWAP=y) 启用 (CONFIG_LV_COLOR_16_SWAP=y)
内存大小 64KB (CONFIG_LV_MEM_SIZE_KILOBYTES=64) 32KB (CONFIG_LV_MEM_SIZE_KILOBYTES=32)
显示缓冲 双缓冲,支持 DMA 双缓冲,支持 DMA
任务优先级 4 4
任务堆栈大小 8192 8192

7.7 显示缓冲区配置对比

配置项 d zbj 项目 QSPI LCD 驱动版本
缓冲区大小计算 LCD_WID*LCD_HIGH/5 EXAMPLE_LCD_H_RES * EXAMPLE_LVGL_DRAW_BUF_LINES (360*30)
内存分配方式 ESP-IDF 标准内存分配 spi_bus_dma_memory_alloc 专门为 SPI DMA 分配
双缓冲 启用 启用
DMA 支持 启用 启用
刷新机制 LVGL 标准刷新 自定义回调 example_notify_lvgl_flush_ready

7.8 UI 文件对比

对比项 d zbj 项目 QSPI LCD 驱动版本
SquareLine Studio 版本 相同版本 相同版本
UI 导出格式 压缩的 PNG 格式 压缩的 PNG 格式
屏幕数量 包含多个屏幕Home、Set、Img 包含多个屏幕Home、Set、Img
图片资源 包含相同的图片资源 包含相同的图片资源
组件结构 完全相同的组件结构 完全相同的组件结构
事件处理 相同的事件处理机制 相同的事件处理机制

7.9 关键差异分析

  1. 内存分配方式

    • qspi_lcd_驱动版本使用 spi_bus_dma_memory_alloc 专门为 SPI DMA 传输分配内存
    • d zbj 项目使用标准内存分配,可能不是最优的 DMA 内存
  2. 显示缓冲区配置

    • qspi_lcd_驱动版本使用固定的 30 行作为缓冲区大小
    • d zbj 项目使用 LCD_WID*LCD_HIGH/5 计算缓冲区大小
  3. 初始化流程

    • qspi_lcd_驱动版本使用管理器模式分层初始化包含详细的错误处理
    • d zbj 项目使用线性初始化流程,错误处理相对简单
  4. 刷新回调

    • qspi_lcd_驱动版本实现了自定义的 example_notify_lvgl_flush_ready 回调
    • d zbj 项目使用 LVGL 标准刷新机制

7.10 花屏问题分析

基于以上对比,导致 d zbj 项目花屏的可能原因包括:

  1. 内存分配问题

    • 未使用 spi_bus_dma_memory_alloc 分配适合 DMA 传输的内存
    • 可能导致 DMA 传输数据错误,引起花屏
  2. 显示缓冲区配置

    • LCD_WID*LCD_HIGH/5 计算出的缓冲区大小可能不合适
    • 缓冲区过小可能导致显示不完整,过大可能导致内存不足
  3. 初始化流程问题

    • 初始化顺序可能影响硬件状态
    • 缺少必要的初始化步骤或延迟
  4. 刷新机制问题

    • 缺少自定义的刷新就绪回调
    • 可能导致 LVGL 与硬件刷新不同步

7. 解决方案

7.1 具体措施

  1. 优化内存分配

    • 使用 spi_bus_dma_memory_alloc 专门为 SPI DMA 传输分配内存
    • 确保内存对齐和连续性,提高 DMA 传输效率
  2. 调整缓冲区配置

    • 参考 QSPI LCD 驱动版本,使用固定行数的缓冲区大小(如 30 行)
    • 确保缓冲区大小合理,避免内存不足或浪费
  3. 改进刷新机制

    • 实现自定义的 notify_lvgl_flush_ready 回调
    • 确保 LVGL 与硬件刷新同步,减少显示异常
  4. 优化初始化流程

    • 参考 QSPI LCD 驱动版本的管理器模式
    • 确保初始化顺序正确,添加必要的延迟
    • 增加详细的错误处理和日志输出

8. 结论

通过对两个项目的详细对比分析,我们发现导致 d zbj 项目花屏的主要原因是:

  1. 内存分配方式不当:未使用专门的 spi_bus_dma_memory_alloc 函数分配适合 DMA 传输的内存
  2. 显示缓冲区配置不合理:缓冲区大小计算方式可能导致内存使用不当
  3. 刷新机制不同步:缺少自定义的刷新就绪回调,可能导致 LVGL 与硬件刷新不同步
  4. 初始化流程差异:初始化顺序和错误处理的差异可能影响硬件状态

采用 QSPI LCD 驱动版本的实现方式,特别是内存分配、缓冲区配置和刷新机制的优化,可以有效解决 d zbj 项目的花屏问题,提高 LVGL 适配的稳定性和可靠性。