正点原子imx6ull移植lvgl v8.3及触摸屏调试

使用正点原子imx6ull移植lvgl 8.3及触摸屏调试过程。

硬件

  • 开发板:ALPHA I.MX6ULL
  • 屏幕:ALIENTEK 7’ RGB TFTLCD 1024*600

软件

已烧录带framebuffer的zImage(cat /dev/fb0可以打开)
如果带触摸,需要确认已存在触摸节点(ls /dev/input/event*),使用hexdump /dev/input/event*可以检测到触摸

lvgl源码下载、修改、编译

  • 创建文件夹mkdir lvgl_imx6ull && cd lvgl_imx6ull
  • 克隆源代码
git clone -b release/v8.3 https://github.com/lvgl/lv_port_linux_frame_buffer.git
git clone -b release/v8.3 https://github.com/lvgl/lvgl.git
git clone -b release/v8.3 https://github.com/lvgl/lv_drivers.git

lvgllv_drivers文件夹复制到lv_port_frame_buffer 文件夹下,文件目录如下:

lv_port_linux_frame_buffer$ tree -L 1
├── LICENSE
├── lv_conf.h
├── lv_drivers
├── lv_drv_conf.h
├── lvgl
├── main.c
├── Makefile
├── mouse_cursor_icon.c
└── README.md

修改Makefile

修改工具链:CC = arm-linux-gnueabihf-gcc
由于驱动教程安装的工具链版本较低,所以后续编译会报错,这里直接为了解决编译错误,直接修改Makefile的CFLAGS

  • 添加-std=gnu99
  • 删除编译选项-Wshift-negative-value

修改lv_drv_conf.h

1. USE_FBDEV

在这里插入图片描述

2. USE_EVDEV

在这里插入图片描述

修改lv_conf.h

1. LV_MEM_CUSTOM

在这里插入图片描述

2. 可选

在这里插入图片描述

修改main.c

在这里插入图片描述

编译

lvgl_imx/lv_port_linux_frame_buffer$ make -j16

编译完后生成可执行文件demo,拷贝至开发板后使用./demo运行即可。

运行效果

在这里插入图片描述
至此,基本移植工作已完成,但是此时触摸完全没反应,接下来开始了调触摸的部分。

触摸调试

这里是使用的Linux内核自带的驱动,edt-ft5x06.c也是使用的正点原子修改过的,理论上不需要再次修改。
使用hexdump /dev/input/event1命令可以确认触摸硬件及驱动都是正常工作的。

evdev_read

main.c已经注册了输入的回调函数,调试的第一步选择在evdev_read函数里添加打印,输出当前坐标位置,检测是否检测到触摸。

void evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
	  ...
	  
	data->state = evdev_button;
	printf("state = %d\n", evdev_button);
	
	if(data->point.x < 0)
	  data->point.x = 0;
	if(data->point.y < 0)
	  data->point.y = 0;
	if(data->point.x >= drv->disp->driver->hor_res)
	  data->point.x = drv->disp->driver->hor_res - 1;
	if(data->point.y >= drv->disp->driver->ver_res)
	  data->point.y = drv->disp->driver->ver_res - 1;
	  
	printf("point.x = %d, point.y = %d\n", data->point.x, data->point.y);
	
	return ;
}

从打印信息里观察到:

state = 0
point.x = 930, point.y = 61
state = 0
point.x = 930, point.y = 61
state = 0
point.x = 930, point.y = 61
...
state = 0
point.x = 593, point.y = 28
state = 0
point.x = 593, point.y = 28
state = 0
point.x = 593, point.y = 28

按下的状态一直为0,但是实际坐标是实时更新的,所以还是这个data->state的问题。

修改驱动文件MAX_SUPPORT_POINTS

看到其他博客中有提到这款屏幕只支持单点触摸,可以把此宏修改为1,然后重新编译内核,可以解决此问题,然而这里修改后并未解决。

#define MAX_SUPPORT_POINTS		1			/* 5点触摸 	*/

此时有些无语了,搞了大半天了。。。

继续跟踪evdev_read

data->state一直为0,说明问题还是出在evdev_read前面的代码里,未满足条件,所以未进行赋值,data->state一直未得到更新。
in.typeinput 子系统 的事件大类,定义在 <linux/input-event-codes.h>
常见 6 种(全部枚举不足 10 种):

数值含义典型事件码
EV_SYN0x00同步事件——用来打包一组数据,本身无意义SYN_REPORT
EV_KEY0x01按键/开关——键盘、鼠标键、触摸按下/释放BTN_TOUCH, KEY_ENTER
EV_REL0x02相对坐标——鼠标、轨迹球REL_X, REL_Y, REL_WHEEL
EV_ABS0x03绝对坐标——触摸屏、游戏摇杆ABS_X, ABS_Y, ABS_MT_POSITION_X
EV_MSC0x04杂项——无标准含义,驱动私有MSC_SCAN, MSC_SERIAL
EV_SW0x05开关——物理滑盖、耳机插入SW_LID, SW_HEADPHONE_INSERT

所以这里只需要关注EV_ABS下的代码:

void evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
    struct input_event in;
    
    while(read(evdev_fd, &in, sizeof(struct input_event)) > 0) {
        printf("read evdev_fd, in.type = %d, in.code = %d\n", in.type, in.code);
        if(in.type == EV_REL) {
			...
        } else if(in.type == EV_ABS) {
            if(in.code == ABS_X)
				#if EVDEV_SWAP_AXES
					evdev_root_y = in.value;
				#else
					evdev_root_x = in.value;
				#endif
            else if(in.code == ABS_Y)
				#if EVDEV_SWAP_AXES
					evdev_root_x = in.value;
				#else
					evdev_root_y = in.value;
				#endif
            else if(in.code == ABS_MT_POSITION_X)
                                #if EVDEV_SWAP_AXES
                                        evdev_root_y = in.value;
                                #else
                                        evdev_root_x = in.value;
                                #endif
            else if(in.code == ABS_MT_POSITION_Y)
                                #if EVDEV_SWAP_AXES
                                        evdev_root_x = in.value;
                                #else
                                        evdev_root_y = in.value;
                                #endif
            else if(in.code == ABS_MT_TRACKING_ID) {
                                if(in.value == -1)
                                    evdev_button = LV_INDEV_STATE_REL;
                                else if(in.value == 0)
                                    evdev_button = LV_INDEV_STATE_PR;
            }
        } else if(in.type == EV_KEY) {
           ...
        }
    }
    ...
}

上述代码里只有in.code==ABS_MT_TRACKING_ID时才会更新evdev_button ,后续再赋值给data->state
继续添加打印信息:

in.code = ABS_MT_TRACKING_ID
in.value = 132
in.code = ABS_MT_POSITION_X
in.value = 606
in.code = ABS_MT_POSITION_Y
in.value = 21
in.code = ABS_X
in.value = 606
in.code = ABS_Y
in.value = 21
state = 1
point.x = 606, point.y = 21
state = 1
point.x = 606, point.y = 21
state = 1
point.x = 606, point.y = 21
in.code = ABS_MT_TRACKING_ID
in.value = -1

从打印信息中基本可以确认问题所在了。可以看到,in.value的值并不是只有-10两种情况,当触摸释放时in.value=-1,但是当按下时会有具体的数值,但不是0 ,所以一直不会把按下的状态置起。
修改代码,再次测试:

 if(in.value == -1)
     evdev_button = LV_INDEV_STATE_REL;
 else /*if(in.value == 0)*/
     evdev_button = LV_INDEV_STATE_PR;

果然,一切正常了,可以愉快的触摸了。
在这里插入图片描述


由于使用的是现成的驱动程序,所以并未从驱动角度深入调试分析,按理说修改驱动应该才是正确方法,但是既然传入的in.value可以是更大范围的数值,那修改lvgl的代码应该也是合理的,如果大家有更好的修改方法也可评论区交流。

### 正点原子 IMX6ULL 移植 LVGL 图形库方法 #### 一、LVGL简介 LVGL (Light and Versatile Graphics Library) 是一款轻量级且功能丰富的嵌入式GUI库,适用于资源受限的微控制器。该库提供了多种控件和主题支持,能够帮助开发者快速构建美观的应用界面。 #### 二、移植准备 为了在IMX6ULL平台上成功移植LVGL图形库,需完成如下准备工作: - **环境搭建**:确保已安装必要的工具链以及依赖项。对于ARM平台而言,通常会采用交叉编译的方式生成目标文件[^2]。 - **获取源码**:访问官方GitHub仓库或其他可信渠道下载最新版本的LVGL源代码包[^1]。 #### 三、具体操作流程 ##### 创建工程项目 基于所使用的IDE或命令行工具建立新的C/C++项目,并导入之前获得的LVGL源文件夹至指定位置。 ##### 修改配置选项 编辑`lv_conf.h`来调整默认参数设置以适应硬件特性;同时还需要根据实际情况定制显示驱动程序接口函数实现部分逻辑处理工作,比如初始化屏幕分辨率等信息。 ```c /* Display buffer size */ #define DISP_BUF_SIZE (320 * 240) static lv_disp_buf_t disp_buf; static lv_color_t buf_1[DISP_BUF_SIZE]; ``` ##### 编写主循环结构体定义 编写应用程序入口处的主要事件轮询机制,用于持续刷新UI组件状态并响应触摸输入动作。 ```c int main(void){ /* Initialize the Littlev GL */ lv_init(); /*Initialize the display*/ my_display_init(); /* Create a display buffer*/ static lv_disp_draw_buf_t draw_buf; lv_disp_draw_buf_init(&draw_btn, buf_1, NULL, DISP_BUF_SIZE); /* Register the display in Littlev gl*/ lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.draw_buf = &draw_buf; disp_drv.flush_cb = my_disp_flush; // Required disp_drv.hor_res = 320; disp_drv.ver_res = 240; lv_disp_drv_register(&disp_drv); while(1){ lv_task_handler(); /* Let the GUI do its tasks */ usleep(5 * 1000); /* Just to avoid 100% CPU usage */ } return 0; } ``` ##### 测试验证阶段 最后一步是在实际设备上部署编译后的可执行文件并通过串口调试等方式确认各项功能是否正常运作。如果遇到任何异常情况,则应回溯至上一步骤仔细排查可能存在的问题所在。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值