转载请标明出处,否则禁止转载。 标题:<玩转树莓派屏幕之四:适配tslib增加触屏准确度> / 作者:longtao 原始文章链接:http://liulongtao.com/index.php/树莓派/113/
由于使用从/dev/input/event0中直接读取数据,在屏幕上显示不准确。并且树莓派的MHS35是旋转90°的,所以导致树莓派的屏幕滑动和实际滑动不符,并且通过更改代码实现一致,也存在点击位置和屏幕显示位置存在偏差的问题。tslib中对从/dev/input/event0数据进行了过滤和矫正,准确性有了大幅度的提升。
一、主要思路
- 安装tslib仓库
- 实现从tslib中读取的方法,注册到lvgl中
- 添加tslib到cmake中
- 添加tslib的全局变量到.bashrc或者/etc/profile中
二、环境配置:
2.1 安装libts-dev开发环境
sudo apt install libts-dev
然后将树莓派的/usr /lib目录复制到WSL环境上,选择指定位置,我这里选择/home/longtao/raspberry/sysroot,用于交叉编译。
检查是否存在
ls /home/longtao/raspberry/sysroot/usr/include/tslib.h
ls /home/longtao/raspberry/sysroot/usr/lib/aarch64-linux-gnu/libts.*
ll /home/longtao/raspberry/sysroot/lib/aarch64-linux-gnu/pkgconfig
2.2 设置交叉编译选项:
设置toolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)set(CMAKE_SYSROOT /home/longtao/raspberry/sysroot)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)# 确保 pkg-config 使用 sysroot
set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_SYSROOT}/usr/lib/aarch64-linux-gnu/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig)
- PKG_CONFIG_LIBDIR: 设置让cmake识别tslib的pkg文件,引入tslib.pc引用。
2.3 设置cmake配置文件
# 查找 tslib
find_package(PkgConfig REQUIRED)
pkg_check_modules(TSLIB REQUIRED IMPORTED_TARGET GLOBAL tslib)message(STATUS "TSLIB include dirs: ${TSLIB_INCLUDE_DIRS}")
message(STATUS "TSLIB include dirs: ${TSLIB_LIBRARY_DIRS}")# 包含 tslib 头文件(自动从 pkg-config 获取)
include_directories(${TSLIB_INCLUDE_DIRS})
link_directories(${TSLIB_LIBRARY_DIRS})add_executable(lvglsim src/main.c ${LV_LINUX_SRC} ${LV_LINUX_BACKEND_SRC})
target_include_directories(lvglsim PRIVATE ${TSLIB_INCLUDE_DIRS})
target_link_libraries(lvglsim lvgl_linux lvgl PkgConfig::TSLIB dl pthread)
- 上面已经把tslib.pc路径让cmake进行识别
- include_directories 和 link_directories 是自动从 pkg-config中获取的
- target_include_directories:目标文件使用TSLIB的路径
- target_link_libraries:执行最后的链接
三、代码实现:
代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>#include "lvgl/lvgl.h"#define LVGL_TICK 5#include <tslib.h>
static struct tsdev *ts;void tsdev_init(void)
{char *tsdevname = getenv("TSLIB_TSDEVICE");if (tsdevname == NULL) {printf("Not found env named: TSLIB_TSDEVICE, %s \n", tsdevname);exit(-1);}printf("TSLIB_TSDEVICE : %s\n", tsdevname);ts = ts_open(tsdevname, 1);if (ts == NULL) {printf("Failed to open tsdev: %s\n", tsdevname);exit(-1);}ts_config(ts);
}/*** Get the current position and state of the tsdev* @param data store the tsdev data here* @return false: because the points are not buffered, so no more data to be read*/
static void tsdev_read(lv_indev_t * indev, lv_indev_data_t * data)
{static struct ts_sample samp;while (ts_read(ts, &samp, 1) == 1) {printf("%ld.%06ld: %6d %6d %6d %d\n",samp.tv.tv_sec, samp.tv.tv_usec,samp.x, samp.y, samp.pressure, data->state);}// printf("%ld.%06ld: %6d %6d %6d %d\n",// samp.tv.tv_sec, samp.tv.tv_usec,// samp.x, samp.y, samp.pressure, data->state);data->point.x = samp.x;data->point.y = samp.y;data->state = samp.pressure ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
}static void event_handler(lv_event_t* e)
{lv_event_code_t code = lv_event_get_code(e);if (code == LV_EVENT_CLICKED){LV_LOG_USER("Clicked");}else if (code == LV_EVENT_VALUE_CHANGED){LV_LOG_USER("Toggled");}
}void lv_example_btn_1(void)
{lv_obj_t* label;lv_obj_t* btn1 = lv_btn_create(lv_scr_act());lv_obj_add_event_cb(btn1, event_handler, LV_EVENT_ALL, NULL);lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -40);label = lv_label_create(btn1);lv_label_set_text(label, "Button");lv_obj_center(label);lv_obj_t* btn2 = lv_btn_create(lv_scr_act());lv_obj_add_event_cb(btn2, event_handler, LV_EVENT_ALL, NULL);lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 40);lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);lv_obj_set_height(btn2, LV_SIZE_CONTENT);label = lv_label_create(btn2);lv_label_set_text(label, "Toggle");lv_obj_center(label);
}int main()
{// 初始化LVGLlv_init();lv_display_t* disp = lv_linux_fbdev_create();lv_linux_fbdev_set_file(disp, "/dev/fb0");tsdev_init();lv_indev_t * indev = lv_indev_create();lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);lv_indev_set_read_cb(indev, tsdev_read);lv_indev_set_display(indev, disp);lv_example_btn_1();while (true){// printf("while\n");usleep(LVGL_TICK); /*Sleep for 5 millisecond*/lv_task_handler();lv_tick_inc(LVGL_TICK); /*Tell LVGL that 5 milliseconds were elapsed*/}
}
展示效果:
root@raspberrypi:~/lcd# ./lvglsim
[Warn] (0.000, +0) lv_init: Memory integrity checks are enabled via LV_USE_ASSERT_MEM_INTEGRITY which makes LVGL much slower lv_init.c:321
[Warn] (0.000, +0) lv_init: Object sanity checks are enabled via LV_USE_ASSERT_OBJ which makes LVGL much slower lv_init.c:325
[Warn] (0.000, +0) lv_init: Style sanity checks are enabled that uses more RAM lv_init.c:329
TSLIB_TSDEVICE : /dev/input/event0
[Warn] (172029.872, +172029872) lv_indev_set_read_cb: lv_indev_set_read_cb: read_cb is: 0x558126c130 lv_indev.c:314
1759772226.129870: 14 21 136 0
1759772226.143604: 13 22 141 01759772227.218917: 473 17 133 0
1759772227.228346: 472 18 138 01759772229.185915: 7 310 118 0
1759772229.199508: 8 310 126 01759772230.120387: 468 302 103 0
1759772230.132073: 468 303 129 01759772230.904041: 243 200 145 0
1759772230.915879: 244 201 0 0
[User] (172037.650, +7778) event_handler: Toggled main.c:352
[User] (172037.651, +1) event_handler: Clicked main.c:348
参考文档:
- https://gitee.com/lqwu675/linux-lvgl/blob/gui-guider/main.c
- https://blog.csdn.net/MOS_JBET/article/details/140488852
- https://blog.csdn.net/qq_36413982/article/details/117308086
- https://zmurder.github.io/lvgl/LVLG%E5%9C%A8%E6%A0%91%E8%8E%93%E6%B4%BE%E4%B8%8A%E7%A7%BB%E6%A4%8D%E5%9F%BA%E4%BA%8E9.3.0/
- https://www.yanwenkai.com/?p=693
- https://blog.gitcode.com/bd65a1bedf4c6696f912124418c8114d.html