LVGL触控设计
触屏架构
LVGL对于输入设备单独使用一个文件lv_port_indev.c来进行管理。
触屏通过#define TOUCHPAD_DEV 1 来进行开启。用户需要设置
touchpad_init(void)
touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
static bool touchpad_is_pressed(void)
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
这几个API来实现使用触控设备对LVGL的输入。
普通触屏架构设计就是直接将对应的API传入供LVGL调用即可。这样可以完成基本的功能,但是如果考虑到调用api占用的CPU和时间开销,这显然是不可以接受的。所以在RTOS的环境下,需要为触控的数据获取单独创建一个线程来进行读取。LVGL只需要在需要获取触控数据的时候去内存读取最新的触控数据即可。这样还可以适配多点触控的环境。
可能有人有疑问,为什么要一直读取呢?这样不会浪费数据吗?这其实也是对LVGL的输入设备的理解不充分。LVGL的输入和输出一样,都是根据宏来控制周期的。输入设备依靠
/*Input device read period in milliseconds*/
#define LV_INDEV_DEF_READ_PERIOD 20 /*[ms]*/
这个宏来控制周期。也就是每20ms(period)进行一次数据读取以及对应的更新。在里面进行阻塞式的数据读取会降低LVGL的帧率,降低动画流畅度。
下面是一个简单的基于时间轴的演示,
时间(ms): 0 5 10 15 20 25
Touch采样: X X X
LVGL读取: R R R R R
touch_task的采样周期为10ms,LVGL的读取周期为5ms。
在0ms/10ms/20ms时,touch_task进行采样。
在5mx/10mx/15mx/20ms/25ms时,LVGL调用API从内存中拷贝触屏数据。
在动画上这样的设计更加流畅,而且也可以在采样后进行滤波,校正坐标。
一个很重要的点:LVGL读取的触屏数据是一个状态,而不是一个瞬时时间。每次的触摸更新应该保证至少被读取一次。
┌──────────────┐
│ Touch IC │ (I2C / SPI / INT)
└──────┬───────┘
│
┌──────▼────────┐
│ Touch Task │ ← 周期 or 中断触发
│ - 读硬件 │
│ - 去抖 / 滤波 │
│ - 坐标校正 │
└──────┬────────┘
│
┌──────▼────────┐
│ Touch Buffer │ ← 共享内存 / 结构体
│ (最新一帧) │
└──────┬────────┘
│
┌──────▼────────┐
│ LVGL indev │ ← lv_indev_read_cb
│ 只拷贝数据 │
└───────────────┘

浙公网安备 33010602011771号