lv_port_indev.c 详情介绍
lv_port_indev.c 是 LVGL 输入移植核心,负责把触摸、按键、编码器等硬件输入上报给 LVGL。
可以把它理解为 3 个阶段:注册输入设备、读取输入数据、映射为 LVGL 事件。
1. 文件职责与执行时序
- 系统初始化时调用
lv_port_indev_init()。 - 在
lv_port_indev_init()中注册 LVGL 输入设备(pointer/keypad/encoder)。 - LVGL 周期性调用
read_cb读取硬件数据。 read_cb将硬件状态转换为 LVGL 统一格式(坐标 + 按下/抬起状态)。
如果注册成功但 read_cb 不触发,通常是输入设备未正确挂到 LVGL 或触摸驱动未正常上报。
2. ra6m3-hmi-board 实现要点
对应文件:bsp/renesas/ra6m3-hmi-board/board/lvgl/lv_port_indev.c
-
触摸芯片与设备
- 使用 GT911;
- 通过
rt_hw_gt911_init("gt911", &cfg)注册 RT-Thread 触摸设备; - 运行时通过
rt_device_find("gt911")获取设备句柄。
-
输入回调
touchpad_read(...)从rt_device_read(...)取一帧触摸数据;- 将
x_coordinate/y_coordinate映射到data->point.x/y; - 将
DOWN/MOVE/UP转换为LV_INDEV_STATE_PR/REL。
-
中断协同
rx_callback(...)收到中断后置位touch_detect_flag并临时关中断;touchpad_read(...)完成读取后重新开中断;- 该机制可减少空读,但要注意中断开关时序。
-
LVGL8/LVGL9 兼容
- LVGL8:
lv_indev_drv_t+lv_indev_drv_register; - LVGL9:
lv_indev_create+lv_indev_set_read_cb。
- LVGL8:
3. ra6m3-ek 当前状态
对应文件:bsp/renesas/ra6m3-ek/board/lvgl/lv_port_indev.c
- 当前
lv_port_indev_init()为空实现; - 说明默认工程没有接入触摸/按键输入,仅具备显示能力;
- 若要交互,需要补充输入设备注册和 read 回调实现。
4. 常改参数与接口
-
触摸总线与设备名
- 例如
cfg.dev_name = "i2c1"; - 换板后优先确认 I2C 控制器名称是否一致。
- 例如
-
INT/RST 引脚
- 例如
INT_PIN、RST_PIN的字符串与硬件引脚定义; - 引脚错误常导致"设备能找到但无触摸事件"。
- 例如
-
坐标范围与方向
RT_TOUCH_CTRL_SET_X_RANGE/RT_TOUCH_CTRL_SET_Y_RANGE;- 若屏幕旋转或镜像,需要在
touchpad_read里加坐标变换。
-
事件去抖与采样策略
- 中断触发 + 回调读取更省 CPU;
- 纯轮询实现更简单,但在高频 UI 下可能增加系统负载。
5. 常见故障与定位
- 点击无效 :检查
lv_port_indev_init()是否被调用、touch_indev是否成功注册。 - 坐标错位:检查分辨率、X/Y 范围和旋转映射是否一致。
- 拖动断续:检查中断关闭/开启时机、I2C 读速率和触摸控制器中断线状态。
- 偶发卡住 :检查
read_data内存申请是否成功、异常路径是否遗漏状态恢复。 - 只有按下没有抬起 :检查
RT_TOUCH_EVENT_UP分支是否覆盖并正确上报REL。
6. 推荐调试步骤(输入链路)
- 先在串口打印触摸原始坐标,确认触摸芯片通信正常;
- 再验证
read_cb被周期调用,且能稳定返回PR/REL; - 再在 LVGL 中测试按钮点击、滑动列表、长按等场景;
- 最后再优化中断与采样参数,平衡响应速度和 CPU 占用。
7. lv_port_indev_init() 详情
lv_port_indev_init() 是输入移植入口函数,作用是把底层输入设备挂到 LVGL。
核心任务可以概括为 4 步:创建 LVGL 输入对象 -> 绑定 read 回调 -> 初始化底层触摸设备 -> 做结果校验。
7.1 通用流程(抽象视角)
-
创建输入设备对象
- LVGL8:
lv_indev_drv_t+lv_indev_drv_init(...); - LVGL9:
lv_indev_create()。
- LVGL8:
-
设置设备类型
- 触摸屏通常使用
LV_INDEV_TYPE_POINTER; - 按键/编码器则是
KEYPAD/ENCODER。
- 触摸屏通常使用
-
绑定读取函数
- 通过
read_cb把硬件事件映射给 LVGL; read_cb至少要正确填充:坐标和PR/REL状态。
- 通过
-
初始化底层驱动
- 完成 I2C/SPI 总线、INT/RST 引脚、触摸芯片注册;
- 初始化失败时应尽早返回并打印日志/断言,避免"无输入但无报错"。
7.2 ra6m3-hmi-board 中的初始化细节
对应:bsp/renesas/ra6m3-hmi-board/board/lvgl/lv_port_indev.c
- LVGL 侧注册:
- LVGL8:
lv_indev_drv_register(&indev_drv); - LVGL9:
lv_indev_create()+lv_indev_set_read_cb(...)。
- LVGL8:
- 底层触摸初始化:
rt_hw_gt911_register()内部设置cfg.dev_name = "i2c1";- 配置
INT_PIN、RST_PIN,调用rt_hw_gt911_init("gt911", &cfg)。
- 探测与能力设置:
gt911_probe(480, 272)设置触摸坐标范围;- 注册
rx_callback接收中断并驱动读取流程。
- 结果校验:
RT_ASSERT(res == RT_EOK)确保触摸初始化失败能被立即发现。
7.3 ra6m3-ek 中的当前情况
对应:bsp/renesas/ra6m3-ek/board/lvgl/lv_port_indev.c
- 当前函数体为空;
- 表示该 BSP 默认不启用输入设备;
- 若要支持触摸,需要补齐以下内容:
- LVGL 输入对象注册;
- 触摸设备初始化(总线、引脚、设备名);
read_cb事件映射;- 初始化结果检查与错误处理。
7.4 这个函数最容易出错的点
- 只注册 LVGL,不初始化硬件 :
read_cb会被调用,但永远读不到有效数据。 - 设备名错误 :如
i2c1与实际总线名不一致,导致rt_device_find失败。 - 类型设置错误 :触摸设备误设为
KEYPAD,会出现事件行为异常。 - 未处理初始化失败:函数继续运行但输入不可用,定位困难。
- 坐标范围未设置:触摸响应存在边缘死区或坐标压缩。
7.5 建议的最小验证法(只测 init)
- 在
lv_port_indev_init()起止位置打日志,确认函数确实执行; - 打印
touch_indev指针和底层设备打开结果; - 上电后点击屏幕,确认
read_cb有持续触发; - 验证一次完整事件序列:
DOWN -> MOVE -> UP。