feat(display): 添加LVGL显示支持和PWM背光控制
添加了完整的LVGL集成支持,包括: - 在app.overlay中配置显示设备树,添加背光别名和SPI3总线支持 - 集成PWM背光控制,通过pwm-leds子系统管理背光亮度 - 配置LVGL自动初始化和工作队列运行模式 - 实现显示模块的工作队列更新机制,包含UI创建和定时刷新 - 添加详细的LVGL移植说明文档,涵盖设备树配置、调试步骤和常见问题 - 调整分区配置以适应LVGL固件大小需求 - 启用MCUBoot bootloader支持OTA功能 该变更使得系统能够在ST7789V显示屏上正常运行LVGL界面,并通过PWM控制背光。
This commit is contained in:
791
docs/lvgl_zephyr_porting_notes.md
Normal file
791
docs/lvgl_zephyr_porting_notes.md
Normal file
@@ -0,0 +1,791 @@
|
||||
# 基于 Zephyr 的 LVGL 移植说明
|
||||
|
||||
## 1. 目标
|
||||
|
||||
本文档记录 `new_kbd` 项目在 `atguigu_mini_keyboard/nrf52840` 板卡上调通 LCD 与 LVGL 的过程,重点覆盖以下内容:
|
||||
|
||||
- 板级设备树需要满足的显示与背光条件
|
||||
- 如何先用最基础的 Zephyr `display` 子系统验证硬件链路
|
||||
- 如何切回 Zephyr 自带的 LVGL 适配层
|
||||
- 当前项目已经落地的关键配置
|
||||
- 常见问题与排查顺序
|
||||
|
||||
本文档对应的工程位置:
|
||||
|
||||
- 应用目录: `E:\projects\new_kbd`
|
||||
- 板卡目录: `E:\extra\boards\atguigu\atguigu_mini_keyboard`
|
||||
|
||||
---
|
||||
|
||||
## 2. 硬件链路确认
|
||||
|
||||
当前板卡上的显示相关资源如下:
|
||||
|
||||
- 面板驱动: `sitronix,st7789v`
|
||||
- 总线: `mipi-dbi-spi`
|
||||
- 显示节点: `st7789v3`
|
||||
- 背光: `pwm_leds/backlight`
|
||||
- 背光 PWM 输出: `pwm0`
|
||||
|
||||
板级 DTS 中的关键节点在:
|
||||
|
||||
- [atguigu_mini_keyboard.dts](E:\extra\boards\atguigu\atguigu_mini_keyboard\atguigu_mini_keyboard.dts)
|
||||
- [atguigu_mini_keyboard-pinctrl.dtsi](E:\extra\boards\atguigu\atguigu_mini_keyboard\atguigu_mini_keyboard-pinctrl.dtsi)
|
||||
|
||||
当前已经确认:
|
||||
|
||||
- 屏幕本身可以通过 Zephyr `display_write()` 正常显示颜色切换画面
|
||||
- 背光不是普通 GPIO 开关,而是 `pwm-leds` 设备
|
||||
- `p0.13` 与当前 LCD 使能无关,已经从显示路径里移除
|
||||
|
||||
这意味着:
|
||||
|
||||
- SPI/MIPI DBI 链路是通的
|
||||
- ST7789V 初始化参数至少在当前板上可用
|
||||
- 背光控制链路是通的
|
||||
- 后续如果 LVGL 出现黑屏,优先怀疑的是 LVGL 初始化、线程模型或对象刷新,而不是底层显示驱动
|
||||
|
||||
---
|
||||
|
||||
## 3. 设备树要求
|
||||
|
||||
应用侧 overlay 在:
|
||||
|
||||
- [app.overlay](E:\projects\new_kbd\app.overlay)
|
||||
|
||||
当前与显示相关的关键要求有三条:
|
||||
|
||||
### 3.1 选择显示设备
|
||||
|
||||
必须在 `chosen` 中指定:
|
||||
|
||||
```dts
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,display = &st7789v3;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
否则 Zephyr 的 `display` 子系统和 LVGL 模块都找不到目标显示设备。
|
||||
|
||||
### 3.2 打开显示控制器和面板节点
|
||||
|
||||
应用 overlay 中需要显式把下面这些节点设为 `okay`:
|
||||
|
||||
```dts
|
||||
&spi2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mipi_dbi {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&st7789v3 {
|
||||
status = "okay";
|
||||
};
|
||||
```
|
||||
|
||||
### 3.3 打开 PWM 背光
|
||||
|
||||
当前背光不是由显示驱动自动管理,而是走 LED/PWM 子系统,所以还需要:
|
||||
|
||||
```dts
|
||||
/ {
|
||||
aliases {
|
||||
backlight = &backlight;
|
||||
};
|
||||
};
|
||||
|
||||
&pwm_leds {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pwm0 {
|
||||
status = "okay";
|
||||
};
|
||||
```
|
||||
|
||||
这样应用代码里可以通过 `LED_DT_SPEC_GET(DT_NODELABEL(backlight))` 拿到背光设备,再调用 `led_set_brightness_dt()` 设亮度。
|
||||
|
||||
---
|
||||
|
||||
## 4. 先验证裸显示,再切回 LVGL
|
||||
|
||||
这次移植采用了两阶段策略:
|
||||
|
||||
### 4.1 第一阶段: 先验证 Zephyr `display` 子系统
|
||||
|
||||
在这个阶段,应用不启用 LVGL,而是直接调用:
|
||||
|
||||
- `display_get_capabilities()`
|
||||
- `display_blanking_off()`
|
||||
- `display_write()`
|
||||
|
||||
通过 RGB565 彩条整屏写入,确认:
|
||||
|
||||
- 面板已经真正收到像素数据
|
||||
- 刷新链路不是空转
|
||||
- 背光与显示内容是解耦的
|
||||
|
||||
这个阶段已经验证成功,屏幕可以正常显示颜色切换画面。
|
||||
|
||||
### 4.2 第二阶段: 切回 Zephyr 自带 LVGL 适配层
|
||||
|
||||
在确认底层链路没问题后,再恢复 LVGL。这样如果再次黑屏,就可以把排查范围收缩到:
|
||||
|
||||
- LVGL 是否真的初始化成功
|
||||
- UI 是否在正确线程创建
|
||||
- 对象是否被正确刷新
|
||||
- `display_blanking_off()` 与背光使能时机是否正确
|
||||
|
||||
这个两阶段方法是这次调试中最关键的分界线。
|
||||
|
||||
---
|
||||
|
||||
## 5. 当前 LVGL 方案
|
||||
|
||||
当前项目使用的是 Zephyr 自带的 LVGL 移植,不再手写 `lv_timer_handler()` 主循环。
|
||||
|
||||
相关应用代码在:
|
||||
|
||||
- [display_module.c](E:\projects\new_kbd\src\modules\display_module.c)
|
||||
|
||||
当前方案要点如下:
|
||||
|
||||
### 5.1 使用 Zephyr 自带的 LVGL 自动初始化
|
||||
|
||||
依赖 `CONFIG_LV_Z_AUTO_INIT=y`,由 Zephyr 在应用启动前完成:
|
||||
|
||||
- `lv_init()`
|
||||
- display 注册
|
||||
- 渲染缓冲区创建
|
||||
- LVGL 核心初始化
|
||||
|
||||
因此应用层不需要再手动调用 `lvgl_init()`。
|
||||
|
||||
### 5.2 使用 Zephyr 的 LVGL workqueue
|
||||
|
||||
依赖 `CONFIG_LV_Z_RUN_LVGL_ON_WORKQUEUE=y`。
|
||||
|
||||
这样 LVGL 核心 `lv_timer_handler()` 由 Zephyr 模块自己调度,应用层不再手动驱动 LVGL 时钟。
|
||||
|
||||
应用里如果还需要定期更新 UI,当前做法是:
|
||||
|
||||
- 自己维护一个 `k_work_delayable`
|
||||
- 通过 `lvgl_get_workqueue()` 把这个 work 投递到 LVGL 专用 workqueue
|
||||
- 在 work 回调里 `lvgl_lock()` 后访问 LVGL API
|
||||
|
||||
这样做的原因是:
|
||||
|
||||
- 避免 UI 更新逻辑和 LVGL 核心不在同一执行上下文
|
||||
- 避免对象创建、样式更新与内部刷新竞争
|
||||
- 对当前板子来说,这是比“任意线程加锁直接操作 LVGL”更保守、更容易稳定的方案
|
||||
|
||||
### 5.3 先开背光,再创建 UI
|
||||
|
||||
当前时序是:
|
||||
|
||||
1. `display_blanking_off()`
|
||||
2. `display_backlight_init()`
|
||||
3. 将显示模块标记为 ready
|
||||
4. 立即在 LVGL workqueue 上调度一次 UI 更新
|
||||
|
||||
背光初始化通过 `pwm-leds` 完成,不再依赖额外 GPIO。
|
||||
|
||||
### 5.4 当前 UI 验证策略
|
||||
|
||||
为了避免“画面有了但刚好看不见”的误判,当前 UI 使用了高对比度方案:
|
||||
|
||||
- 背景色在两种颜色之间切换
|
||||
- 标题为 `Zephyr LVGL running`
|
||||
- 计数文本为 `tick N`
|
||||
|
||||
如果这三项都能显示,基本可以判定 LVGL 渲染链路已经正常工作。
|
||||
|
||||
---
|
||||
|
||||
## 6. 当前关键配置
|
||||
|
||||
应用配置文件在:
|
||||
|
||||
- [prj.conf](E:\projects\new_kbd\prj.conf)
|
||||
|
||||
当前与 LVGL/显示相关的关键配置如下:
|
||||
|
||||
```conf
|
||||
CONFIG_DISPLAY=y
|
||||
CONFIG_MIPI_DBI=y
|
||||
CONFIG_ST7789V=y
|
||||
|
||||
CONFIG_LVGL=y
|
||||
CONFIG_LV_CONF_MINIMAL=y
|
||||
CONFIG_LV_BUILD_EXAMPLES=n
|
||||
CONFIG_LV_BUILD_DEMOS=n
|
||||
CONFIG_LV_USE_LABEL=y
|
||||
CONFIG_LV_FONT_MONTSERRAT_14=y
|
||||
|
||||
CONFIG_LV_Z_AUTO_INIT=y
|
||||
CONFIG_LV_Z_BITS_PER_PIXEL=16
|
||||
CONFIG_LV_Z_LVGL_MUTEX=y
|
||||
CONFIG_LV_Z_RUN_LVGL_ON_WORKQUEUE=y
|
||||
CONFIG_LV_Z_MEM_POOL_SIZE=16384
|
||||
```
|
||||
|
||||
各项含义:
|
||||
|
||||
- `CONFIG_LV_Z_BITS_PER_PIXEL=16`
|
||||
与 ST7789V 当前 `RGB565` 像素格式对应,避免渲染缓冲格式不匹配
|
||||
|
||||
- `CONFIG_LV_Z_LVGL_MUTEX=y`
|
||||
提供 `lvgl_lock()` / `lvgl_unlock()`,确保应用层访问 LVGL API 时有统一互斥保护
|
||||
|
||||
- `CONFIG_LV_Z_RUN_LVGL_ON_WORKQUEUE=y`
|
||||
让 Zephyr 自动维护 LVGL 核心执行循环,不需要应用手动跑 `lv_timer_handler()`
|
||||
|
||||
- `CONFIG_LV_Z_MEM_POOL_SIZE=16384`
|
||||
作为当前最小可工作的内存池配置
|
||||
|
||||
---
|
||||
|
||||
## 7. 构建方式
|
||||
|
||||
当前构建已不再默认强制使用 `-Og`,而是遵从工程自身配置。
|
||||
|
||||
当前工程已经启用:
|
||||
|
||||
```conf
|
||||
CONFIG_SIZE_OPTIMIZATIONS=y
|
||||
```
|
||||
|
||||
因此默认会走 size optimization,适合当前 OTA 分区大小约束。
|
||||
|
||||
### 7.1 当前构建 skill 的行为
|
||||
|
||||
`ncs-fresh-build` skill 已经调整为:
|
||||
|
||||
- 不再默认注入 `CONFIG_DEBUG_OPTIMIZATIONS=y`
|
||||
- 默认构建目录为项目根下的 `build`
|
||||
- 如果项目下已有 `build` 且带构建元数据,则执行 `resume build`
|
||||
- 如果不存在,则在项目根下创建 `build`
|
||||
|
||||
也就是说,当前默认构建输出目录是:
|
||||
|
||||
- `E:\projects\new_kbd\build`
|
||||
|
||||
### 7.2 当前已验证的构建结果
|
||||
|
||||
在当前 LVGL 配置下,系统构建通过,成功产出:
|
||||
|
||||
- `merged.hex`
|
||||
- `dfu_application.zip`
|
||||
|
||||
最近一次 LVGL 镜像的资源占用约为:
|
||||
|
||||
- FLASH: `437780 / 482816`
|
||||
- RAM: `96052 / 256 KB`
|
||||
|
||||
说明在当前 OTA 分区布局下,LVGL 版本仍然可以装下。
|
||||
|
||||
---
|
||||
|
||||
## 8. 当前显示模块代码结构
|
||||
|
||||
当前显示模块入口在:
|
||||
|
||||
- [display_module.c](E:\projects\new_kbd\src\modules\display_module.c)
|
||||
|
||||
整体逻辑如下:
|
||||
|
||||
1. 等待 `main` 模块进入 `MODULE_STATE_READY`
|
||||
2. 检查显示设备是否 ready
|
||||
3. 读取显示能力并打印日志
|
||||
4. 调用 `display_blanking_off()`
|
||||
5. 初始化背光 PWM 亮度
|
||||
6. 将模块标记为 initialized
|
||||
7. 把第一个 UI 更新 work 投递到 LVGL workqueue
|
||||
8. 后续每秒更新一次背景与计数文本
|
||||
|
||||
这种结构的好处是:
|
||||
|
||||
- 显示模块与主应用启动顺序解耦
|
||||
- LVGL 核心循环交给 Zephyr 模块维护
|
||||
- 应用只负责自己的 UI 逻辑
|
||||
- 以后如果要继续扩展页面,也可以沿用同样的工作队列模型
|
||||
|
||||
---
|
||||
|
||||
## 9. 常见问题与排查顺序
|
||||
|
||||
### 9.1 背光亮,但完全黑屏
|
||||
|
||||
先不要怀疑 LVGL,先切回裸 `display_write()` 测试版本。
|
||||
|
||||
如果裸显示也黑屏,优先检查:
|
||||
|
||||
- `zephyr,display` 是否指向正确节点
|
||||
- `spi2` / `mipi_dbi` / `st7789v3` 是否都为 `okay`
|
||||
- ST7789V 初始化参数是否匹配当前屏
|
||||
- 面板 offset / colmod / madctl 是否正确
|
||||
|
||||
### 9.2 裸 `display_write()` 正常,但 LVGL 黑屏
|
||||
|
||||
优先检查:
|
||||
|
||||
- `CONFIG_LV_Z_RUN_LVGL_ON_WORKQUEUE` 是否启用
|
||||
- 应用是否仍在手动调用 `lv_timer_handler()`
|
||||
- UI 更新是否发生在错误线程
|
||||
- 是否遗漏 `lvgl_lock()`
|
||||
- 文本和背景颜色是否刚好一致
|
||||
|
||||
### 9.3 背光不亮
|
||||
|
||||
优先检查:
|
||||
|
||||
- `backlight` alias 是否存在
|
||||
- `&pwm_leds` 是否启用
|
||||
- `&pwm0` 是否启用
|
||||
- `pwm0_default` 的 pinctrl 是否正确
|
||||
- 应用是否真的调用了 `led_set_brightness_dt()`
|
||||
|
||||
### 9.4 构建能过,但镜像塞不进 OTA 分区
|
||||
|
||||
优先检查:
|
||||
|
||||
- 是否误用了 `-Og`
|
||||
- `CONFIG_SIZE_OPTIMIZATIONS` 是否生效
|
||||
- 是否启用了不必要的 LVGL demos/examples
|
||||
- 字体、部件和日志级别是否过大
|
||||
|
||||
---
|
||||
|
||||
## 10. 后续建议
|
||||
|
||||
如果后续继续完善显示功能,建议按下面顺序推进:
|
||||
|
||||
1. 先固定当前最小可工作 UI,不要同时引入太多控件
|
||||
2. 增加 RTT 日志,确认 LVGL 初始化和周期更新是否稳定
|
||||
3. 再逐步接入输入设备或更复杂页面
|
||||
4. 最后再考虑动画、图片资源和更大的字体
|
||||
|
||||
对当前项目来说,最重要的经验是:
|
||||
|
||||
- 先把底层 `display` 写屏跑通
|
||||
- 再把问题收敛到 LVGL
|
||||
- 最后再处理更高层的 UI 逻辑
|
||||
|
||||
这样可以显著降低显示移植的排查成本。
|
||||
|
||||
---
|
||||
|
||||
## 11. ST7789V 设备树参数详细说明
|
||||
|
||||
当前板上显示节点位于:
|
||||
|
||||
- [atguigu_mini_keyboard.dts](E:\extra\boards\atguigu\atguigu_mini_keyboard\atguigu_mini_keyboard.dts)
|
||||
|
||||
典型配置如下:
|
||||
|
||||
```dts
|
||||
st7789v3: st7789v@0 {
|
||||
compatible = "sitronix,st7789v";
|
||||
status = "disabled";
|
||||
reg = <0>;
|
||||
mipi-max-frequency = <32000000>;
|
||||
width = <320>;
|
||||
height = <172>;
|
||||
x-offset = <0>;
|
||||
y-offset = <34>;
|
||||
vcom = <0x2b>;
|
||||
gctrl = <0x35>;
|
||||
vrhs = <0x11>;
|
||||
vdvs = <0x20>;
|
||||
mdac = <0x60>;
|
||||
lcm = <0x2c>;
|
||||
colmod = <0x55>;
|
||||
gamma = <0x01>;
|
||||
porch-param = [ 0c 0c 00 33 33 ];
|
||||
cmd2en-param = [ 5a 69 02 01 ];
|
||||
pwctrl1-param = [ a4 a1 ];
|
||||
pvgam-param = [ d0 00 02 07 0a 28 32 44 42 06 0e 12 14 17 ];
|
||||
nvgam-param = [ d0 00 02 07 0a 28 31 54 47 0e 1c 17 1b 1e ];
|
||||
ram-param = [ 00 f0 ];
|
||||
rgb-param = [ c0 02 14 ];
|
||||
mipi-mode = "MIPI_DBI_MODE_SPI_4WIRE";
|
||||
};
|
||||
```
|
||||
|
||||
下面按类别说明这些参数的意义。
|
||||
|
||||
### 11.1 设备身份与总线绑定
|
||||
|
||||
#### `compatible = "sitronix,st7789v"`
|
||||
|
||||
作用:
|
||||
|
||||
- 告诉 Zephyr 使用 ST7789V 显示驱动
|
||||
- 绑定文件来自 [sitronix,st7789v.yaml](C:\ncs\v3.2.3\zephyr\dts\bindings\display\sitronix,st7789v.yaml)
|
||||
- 驱动实现位于 [display_st7789v.c](C:\ncs\v3.2.3\zephyr\drivers\display\display_st7789v.c)
|
||||
|
||||
如果这个 `compatible` 不对,后续所有参数即使写对也不会被正确解释。
|
||||
|
||||
#### `reg = <0>`
|
||||
|
||||
作用:
|
||||
|
||||
- 这是该显示器在父 `mipi_dbi` 总线上的片选号/地址索引
|
||||
- 对 SPI 模式来说,它最终会映射到父 SPI 控制器 `cs-gpios` 数组中的第几个片选
|
||||
|
||||
当前值是 `0`,表示使用父 SPI 控制器的第 0 个 CS。
|
||||
|
||||
#### `mipi-mode = "MIPI_DBI_MODE_SPI_4WIRE"`
|
||||
|
||||
作用:
|
||||
|
||||
- 指定 ST7789V 通过 MIPI DBI Type-C 的 4 线 SPI 模式工作
|
||||
- 命令/数据区分不是靠 9-bit SPI,而是靠单独的 `dc-gpios`
|
||||
|
||||
这对当前板子很重要,因为板上已经专门引出了 DC GPIO。
|
||||
|
||||
#### `mipi-max-frequency = <32000000>`
|
||||
|
||||
作用:
|
||||
|
||||
- 指定面板接口希望使用的最高 SPI 时钟
|
||||
- 这个值会进入 `struct spi_config.frequency`
|
||||
- 最终实际频率还会受底层 SPI 控制器实例上限限制
|
||||
|
||||
当前项目中:
|
||||
|
||||
- 面板这里写的是 `32 MHz`
|
||||
- 底层已经把 LCD 切到 `spi3`
|
||||
- `spi3` 是 nRF52840 上支持 `32 MHz` 的高速 SPIM 实例
|
||||
|
||||
因此这个值现在是有效的,不再像早期挂在 `spi2` 时那样被 SoC 侧 `8 MHz` 上限卡住。
|
||||
|
||||
---
|
||||
|
||||
### 11.2 分辨率与有效显示窗口
|
||||
|
||||
#### `width = <320>`
|
||||
|
||||
作用:
|
||||
|
||||
- Zephyr `display_get_capabilities()` 返回的水平分辨率
|
||||
- LVGL 也会按这个宽度创建显示对象和渲染缓冲
|
||||
|
||||
在当前横屏模式下,宽度已经从竖屏时的 `172` 改为 `320`。
|
||||
|
||||
#### `height = <172>`
|
||||
|
||||
作用:
|
||||
|
||||
- Zephyr `display_get_capabilities()` 返回的垂直分辨率
|
||||
- 决定应用层看到的逻辑屏高
|
||||
|
||||
在当前横屏模式下,高度已经从竖屏时的 `320` 改为 `172`。
|
||||
|
||||
#### `x-offset = <0>`
|
||||
|
||||
作用:
|
||||
|
||||
- 指定 LCD 实际可视窗口在 ST7789V GRAM 中的列偏移
|
||||
- 驱动在写入时,会把应用层传入的 `x` 坐标再加上这个偏移
|
||||
|
||||
对应驱动代码:
|
||||
|
||||
- `st7789v_set_lcd_margins()`
|
||||
- `st7789v_set_mem_area()`
|
||||
|
||||
#### `y-offset = <34>`
|
||||
|
||||
作用:
|
||||
|
||||
- 指定 LCD 实际可视窗口在 ST7789V GRAM 中的行偏移
|
||||
- 驱动会把应用层传入的 `y` 坐标再加上这个偏移
|
||||
|
||||
为什么横屏时从 `x-offset=34` 变成 `y-offset=34`:
|
||||
|
||||
- 这块屏的物理可视区域不是完整的 240x320,而是裁剪出来的 `172x320`
|
||||
- 当通过 `mdac` 做 XY 轴交换后,原来沿 X 方向的裁剪,需要同步转移到 Y 方向
|
||||
|
||||
这是横屏改造里最容易遗漏的一点。如果只改 `width/height` 和 `mdac`,不改 offset,画面通常会出现:
|
||||
|
||||
- 偏移错位
|
||||
- 局部黑边
|
||||
- 显示越界
|
||||
|
||||
---
|
||||
|
||||
### 11.3 方向控制
|
||||
|
||||
#### `mdac = <0x60>`
|
||||
|
||||
作用:
|
||||
|
||||
- 对应 ST7789V 的 `MADCTL` 寄存器,即 Memory Data Access Control
|
||||
- 用于控制:
|
||||
- X/Y 轴交换
|
||||
- 左右镜像
|
||||
- 上下镜像
|
||||
- RGB/BGR 顺序
|
||||
|
||||
对应驱动里的寄存器命令:
|
||||
|
||||
- `ST7789V_CMD_MADCTL`
|
||||
|
||||
当前值 `0x60` 的核心意义是:
|
||||
|
||||
- 打开 `MV`,进行 XY 轴交换
|
||||
- 再配合镜像位,把竖屏坐标系旋转为横屏
|
||||
|
||||
对当前项目来说,`mdac` 是“横竖屏切换的核心参数”。
|
||||
|
||||
如果上板后发现:
|
||||
|
||||
- 画面已经横过来,但方向反了
|
||||
- 或左右/上下镜像不对
|
||||
|
||||
通常只需要继续调整 `mdac`,而不一定需要再动 `width/height`。
|
||||
|
||||
---
|
||||
|
||||
### 11.4 面板电气与模拟参数
|
||||
|
||||
下面这几项大多属于“面板电气初始化参数”,通常来自原厂例程、模组 demo、已有验证过的初始化序列,或者靠经验调通。
|
||||
|
||||
它们的共同特点是:
|
||||
|
||||
- 不建议随便改
|
||||
- 改错后往往不是“完全不亮”,而是
|
||||
- 偏色
|
||||
- 闪烁
|
||||
- 对比度差
|
||||
- 稳定性差
|
||||
- 局部异常
|
||||
|
||||
#### `vcom = <0x2b>`
|
||||
|
||||
作用:
|
||||
|
||||
- VCOM 电压相关设置
|
||||
- 影响液晶驱动偏置和整体显示稳定性
|
||||
|
||||
常见现象:
|
||||
|
||||
- 值不合适时,可能出现闪烁、灰阶异常、残影或对比度不自然
|
||||
|
||||
#### `gctrl = <0x35>`
|
||||
|
||||
作用:
|
||||
|
||||
- Gate Control,控制面板栅极驱动相关参数
|
||||
|
||||
它更接近面板扫描电路的底层设置,一般按已知可工作配置保留。
|
||||
|
||||
#### `vrhs = <0x11>`
|
||||
|
||||
作用:
|
||||
|
||||
- VRH setting,电压参考相关参数之一
|
||||
|
||||
#### `vdvs = <0x20>`
|
||||
|
||||
作用:
|
||||
|
||||
- VDV setting,和驱动电压微调相关
|
||||
|
||||
注意:
|
||||
|
||||
- 驱动里只有同时存在 `vrhs` 和 `vdvs` 时,才会开启对应的 `VDVVRHEN` 流程
|
||||
|
||||
#### `lcm = <0x2c>`
|
||||
|
||||
作用:
|
||||
|
||||
- LCM control,面板控制相关寄存器值
|
||||
|
||||
一般与模组硬件特性绑定,不建议脱离原配置单独尝试。
|
||||
|
||||
#### `gamma = <0x01>`
|
||||
|
||||
作用:
|
||||
|
||||
- Gamma curve 选择
|
||||
- 会影响亮度过渡、灰阶、色彩观感
|
||||
|
||||
---
|
||||
|
||||
### 11.5 像素格式与颜色相关
|
||||
|
||||
#### `colmod = <0x55>`
|
||||
|
||||
作用:
|
||||
|
||||
- 对应 `COLMOD`,即 Interface Pixel Format
|
||||
- 决定总线传输的像素位宽
|
||||
|
||||
当前值 `0x55` 表示 `RGB565 / 16-bit` 模式,这与当前软件配置完全一致:
|
||||
|
||||
- `CONFIG_ST7789V_RGB565=y`
|
||||
- `CONFIG_LV_Z_BITS_PER_PIXEL=16`
|
||||
|
||||
如果这里和软件配置不匹配,常见现象包括:
|
||||
|
||||
- 颜色错乱
|
||||
- 红蓝交换
|
||||
- 图像看起来像“马赛克”或数据错位
|
||||
|
||||
#### `ram-param = [ 00 f0 ]`
|
||||
|
||||
作用:
|
||||
|
||||
- 对应 `RAMCTRL`
|
||||
- 控制显示 RAM 访问的一些底层行为
|
||||
|
||||
这类参数通常和像素格式、总线模式、厂商推荐初始化序列成组使用。
|
||||
|
||||
#### `rgb-param = [ c0 02 14 ]`
|
||||
|
||||
作用:
|
||||
|
||||
- 对应 `RGBCTRL`
|
||||
- 设置 RGB 接口/时序相关参数
|
||||
|
||||
虽然当前走的是 SPI MIPI DBI,不是传统 RGB 并口,但 ST7789V 仍要求这组寄存器初始化。
|
||||
|
||||
---
|
||||
|
||||
### 11.6 时序与前后肩参数
|
||||
|
||||
#### `porch-param = [ 0c 0c 00 33 33 ]`
|
||||
|
||||
作用:
|
||||
|
||||
- 对应 `PORCTRL`
|
||||
- 设置 porch,也就是显示时序中的前后肩、空白区参数
|
||||
|
||||
这些参数会影响:
|
||||
|
||||
- 帧时序稳定性
|
||||
- 扫描边界
|
||||
- 某些情况下的闪烁或边缘异常
|
||||
|
||||
这组值一般与具体模组匹配,建议保留已有验证值。
|
||||
|
||||
---
|
||||
|
||||
### 11.7 扩展命令与电源控制参数
|
||||
|
||||
#### `cmd2en-param = [ 5a 69 02 01 ]`
|
||||
|
||||
作用:
|
||||
|
||||
- 对应 `CMD2EN`
|
||||
- 开启 ST7789V 扩展命令页
|
||||
|
||||
如果这一步配置错误,后面某些扩展寄存器写入可能根本不会生效。
|
||||
|
||||
#### `pwctrl1-param = [ a4 a1 ]`
|
||||
|
||||
作用:
|
||||
|
||||
- 对应 `PWCTRL1`
|
||||
- 电源控制相关参数
|
||||
|
||||
这会影响面板驱动供电行为和显示稳定性。
|
||||
|
||||
---
|
||||
|
||||
### 11.8 Gamma 曲线表
|
||||
|
||||
#### `pvgam-param = [ d0 00 02 07 0a 28 32 44 42 06 0e 12 14 17 ]`
|
||||
|
||||
作用:
|
||||
|
||||
- 对应 `PVGAMCTRL`
|
||||
- Positive Voltage Gamma Control 参数表
|
||||
|
||||
#### `nvgam-param = [ d0 00 02 07 0a 28 31 54 47 0e 1c 17 1b 1e ]`
|
||||
|
||||
作用:
|
||||
|
||||
- 对应 `NVGAMCTRL`
|
||||
- Negative Voltage Gamma Control 参数表
|
||||
|
||||
这两组参数共同决定:
|
||||
|
||||
- 亮暗过渡
|
||||
- 色调倾向
|
||||
- 灰阶表现
|
||||
|
||||
调这些参数通常属于“画质微调”,不是基础 bring-up 阶段的首选手段。除非当前已经能稳定显示,只是观感明显不对,否则不建议优先改这里。
|
||||
|
||||
---
|
||||
|
||||
### 11.9 这些参数里最关键、最常改的是哪些
|
||||
|
||||
在实际移植中,最常需要改的是下面这几项:
|
||||
|
||||
- `width`
|
||||
- `height`
|
||||
- `x-offset`
|
||||
- `y-offset`
|
||||
- `mdac`
|
||||
- `mipi-max-frequency`
|
||||
- `colmod`
|
||||
|
||||
其中:
|
||||
|
||||
- `width/height/x-offset/y-offset/mdac`
|
||||
主要决定方向、有效显示区域和坐标映射
|
||||
|
||||
- `mipi-max-frequency`
|
||||
主要决定带宽上限
|
||||
|
||||
- `colmod`
|
||||
主要决定像素格式是否与软件配置匹配
|
||||
|
||||
而像下面这些:
|
||||
|
||||
- `vcom`
|
||||
- `gctrl`
|
||||
- `vrhs`
|
||||
- `vdvs`
|
||||
- `lcm`
|
||||
- `gamma`
|
||||
- `porch-param`
|
||||
- `cmd2en-param`
|
||||
- `pwctrl1-param`
|
||||
- `pvgam-param`
|
||||
- `nvgam-param`
|
||||
- `ram-param`
|
||||
- `rgb-param`
|
||||
|
||||
更像是“面板模组初始化模板的一部分”,通常是在已有可工作基础上尽量保持不动。
|
||||
|
||||
---
|
||||
|
||||
### 11.10 当前项目的实用建议
|
||||
|
||||
对当前这块屏来说,后续如果还要继续调整显示方向或显示区域,建议按下面顺序操作:
|
||||
|
||||
1. 先改 `mdac`
|
||||
2. 再配套检查 `width/height`
|
||||
3. 最后再修 `x-offset/y-offset`
|
||||
|
||||
不要一上来同时改所有寄存器,否则很难判断到底是哪一项导致了:
|
||||
|
||||
- 图像颠倒
|
||||
- 画面偏移
|
||||
- 部分区域黑边
|
||||
- 写入越界
|
||||
|
||||
对当前项目,真正应该高频修改的设备树参数,其实主要就是这 5 项:
|
||||
|
||||
- `width`
|
||||
- `height`
|
||||
- `x-offset`
|
||||
- `y-offset`
|
||||
- `mdac`
|
||||
Reference in New Issue
Block a user