12. input子系统:触摸屏¶
在上节内容中,已经讲解到了如何使用input输入子系统读取按键值, 触摸屏也是属于input输入子系统的设备,关于input输入子系统 的内容请参考 input子系统:按键检测
12.1. 电容触摸屏¶
12.1.1. 使能电容触摸屏相关设备树插件¶
野火imx6ull提供了很多的设备树插件,用于控制板子上外设的开启,默认状态下开启7寸触摸屏相关插件, 如果不能触摸需要确认触摸屏相关的设备树插件。修改 /boot/uEnv.txt 文件内容, 使能触摸屏设备树相关插件内容以及i2c1设备树插件并重启开发板。
如果是7寸屏幕修改
1 2 3 | dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-i2c1.dtbo
dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-touch-capacitive-goodix.dtbo
#dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-touch-capacitive-gt1151.dtbo
|
如果是4.3、5寸屏幕修改
1 2 3 | dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-i2c1.dtbo
#dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-touch-capacitive-goodix.dtbo
dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-touch-capacitive-gt1151.dtbo
|
查看 /dev/input 以及 /dev/input/by-path 目录下的内容
1 2 3 4 5 6 7 8 9 | root@npi:/# ls -l /dev/input/
total 0
drwxr-xr-x 2 root root 80 Feb 1 11:30 by-path
crw-rw---- 1 root input 13, 64 Feb 1 11:30 event0
crw-rw---- 1 root input 13, 65 Feb 1 11:30 event1
root@npi:/# ls -l /dev/input/by-path/
total 0
lrwxrwxrwx 1 root root 9 Feb 1 11:30 platform-20cc000.snvs:snvs-powerkey-event -> ../event0
lrwxrwxrwx 1 root root 9 Feb 1 11:30 platform-21a0000.i2c-event -> ../event1
|
可知其中触摸屏设备对应的是 event1 ,不同板子情况可能不同。
12.1.2. 使用evtest测试屏幕¶
通过以下命令下载evtest工具
1 | sudo apt install evtest
|
在终端上执行evtest命令并选择触摸屏进行测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | root@npi:/home/zhan# evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: 20cc000.snvs:snvs-powerkey
/dev/input/event1: Goodix Capacitive TouchScreen
Select the device event number [0-1]: 1
Input driver version is 1.0.1
Input device ID: bus 0x18 vendor 0x416 product 0x1001 version 0x200
Input device name: "Goodix Capacitive TouchScreen"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 125 (KEY_LEFTMETA)
Event code 330 (BTN_TOUCH)
Event type 3 (EV_ABS)
Event code 0 (ABS_X)
Value 228
Min 0
Max 5129
Event code 1 (ABS_Y)
Value 269
Min 0
Max 35640
Event code 47 (ABS_MT_SLOT)
Value 0
Min 0
Max 13
Event code 48 (ABS_MT_TOUCH_MAJOR)
Value 0
Min 0
Max 255
Event code 50 (ABS_MT_WIDTH_MAJOR)
Value 0
Min 0
Max 255
Event code 53 (ABS_MT_POSITION_X)
Value 0
Min 0
Max 5129
Event code 54 (ABS_MT_POSITION_Y)
Value 0
Min 0
Max 35640
Event code 57 (ABS_MT_TRACKING_ID)
Value 0
Min 0
Max 65535
Properties:
Property type 1 (INPUT_PROP_DIRECT)
Testing ... (interrupt to exit)
Event: time 1612171395.722485, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 348
Event: time 1612171395.722485, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 438
Event: time 1612171395.722485, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 167
Event: time 1612171395.722485, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 63
Event: time 1612171395.722485, type 3 (EV_ABS), code 50 (ABS_MT_WIDTH_MAJOR), value 63
Event: time 1612171395.722485, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1612171395.722485, type 3 (EV_ABS), code 0 (ABS_X), value 438
Event: time 1612171395.722485, type 3 (EV_ABS), code 1 (ABS_Y), value 167
Event: time 1612171395.722485, -------------- SYN_REPORT ------------
Event: time 1612171395.764640, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value -1
Event: time 1612171395.764640, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0
Event: time 1612171395.764640, -------------- SYN_REPORT ------------
|
根据以上信息即可知道当触摸屏幕时有什么事件产生。
12.1.3. 编写应用程序¶
触摸屏检测相关的应用程序与按键检测的应用程序类似,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <linux/input-event-codes.h>
#include <unistd.h>
#define default_path "/dev/input/event1"
int main(int argc,char * argv[])
{
int fd;
int ret;
char * path;
struct input_event event;
int x,y;
if (argc == 2)
{
path = argv[1];
}
else
{
path = default_path;
}
//打开设备
fd = open(path,O_RDONLY);
if(fd < 0)
{
perror(path);
exit(-1);
}
while (1)
{
memset(&event, 0, sizeof(struct input_event));
//读取按键值
ret = read(fd,&event,sizeof(struct input_event));
if (ret == sizeof(struct input_event))
{
//触发事件类似判断
if(event.type == EV_ABS)
{
//X、Y轴坐标
if(event.code == ABS_X)
x = event.value;
else if(event.code == ABS_Y)
y = event.value;
}
//打印坐标
if(event.type == EV_SYN) //EV_SYN
{
printf("touch x = %d,y = %d\n", x, y);
}
}
}
close(fd);
return 0;
}
|
运行程序后,触摸屏将不断打印坐标信息。
12.1.4. 使用libts工具重新校准电容屏¶
电容屏是不需要重新校准的,读取出来的原始数据就是坐标值了, libts是一种实用的触摸工具,能够用于触摸屏的校准,将触摸位置与屏幕显示位置统一起来。
其中需要开启显示屏相关设备树插件,关于显示屏相关配置请移步 屏幕显示 章节。
通过以下命令下载libts-bin工具
1 | sudo apt install libts-bin
|
使用以下命令进行屏幕校准,执行以下两条命令之后,显示屏将会显示需要点击的位置, 依次点击完成后完成屏幕
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #设置环境变量,并将/dev/input/event1替换为自己的触摸输入设备
export TSLIB_TSDEVICE=/dev/input/event1 #这条命令建议手打
#进行屏幕校准
ts_calibrate
#终端打印消息
xres = 800, yres = 480
Took 1 samples...
Top left : X = 68 Y = 49
Took 1 samples...
Top right : X = 749 Y = 36
Took 1 samples...
Bot right : X = 757 Y = 421
Took 1 samples...
Bot left : X = 48 Y = 420
Took 1 samples...
Center : X = 397 Y = 234
-10.113098 1.006793 0.015388
3.398499 0.008502 1.005036
Calibration constants: -662772 65981 1008 222724 557 65866 65536
|
提示
如果用不带qt的镜像,直接使用上面命令测试,屏幕会依次出现5个点,依次按压就会打印消息;如果是带qt的镜像,使用命令sudo systemctl disable ebf-qtdemo关闭下qt服务,,然后重启下,就可以使用上面命令测试。
执行ts_print命令后触摸触摸屏将会打印出相对应的坐标,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #执行命令
ts_print
#打印消息
1620870796.103364: 10 24 255
1620870796.160909: 10 24 0
1620870797.208897: 768 28 255
1620870797.276258: 768 28 0
1620870798.258659: 769 452 255
1620870798.326248: 769 452 0
1620870799.431149: 26 427 255
1620870799.462790: 26 427 0
1620870800.514642: 396 250 255
1620870800.571719: 396 250 0
|
关于libts工具使用的详细说明可参考以下链接: https://github.com/libts/tslib
12.1.5. 触摸屏相关设备树插件¶
野火imx6ull提供了很多的设备树插件源码,若想要修改触摸屏设备树插件, 可参考:
其中触摸屏的设备树插件为 imx-fire-touch-capacitive-goodix-overlay.dts ,源码如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include "imx6ul-pinfunc.h"
#include "imx6ull-pinfunc-snvs.h"
#include "dt-bindings/interrupt-controller/irq.h"
#include "dt-bindings/gpio/gpio.h"
/dts-v1/;
/plugin/;
/ {
compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
fragment@0 {
target = <&i2c1>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
gtxx_tsc@5d {
compatible = "goodix,gt9157","goodix,gt917s","goodix,gt5688";
pinctrl-0 = <&pinctrl_tsc_reset>;
pinctrl-1 = <&pinctrl_tsc_irq>;
reg = <0x5d>;
status = "okay";
/*gpio*/
reset-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>;
irq-gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>;
/*interrupt*/
interrupt-parent = <&gpio5>;
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
irq-flags = <2>; /*1:rising 2: falling*/
};
};
};
fragment@1 {
target = <&iomuxc>;
__overlay__ {
pinctrl_tsc_reset: tscresetgrp {
fsl,pins = <
/* used for tsc reset */
MX6UL_PAD_LCD_RESET__GPIO3_IO04 0x05
>;
};
};
};
fragment@2 {
target = <&iomuxc_snvs>;
__overlay__ {
pinctrl_tsc_irq: tsc_irq {
fsl,pins = <
MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x4001b8b0
>;
};
};
};
};
|
若想修改触摸屏控制芯片相关引脚,仅需要修改以上高亮部分代码即可。
12.2. 电阻触摸屏¶
除了能够使用电容触摸屏之外,野火Linux开发板也支持电阻触摸屏设备, 想要使用电阻触摸屏,可修改修改 /boot/uEnv.txt 文件内容,使能电阻触摸屏相关设备树插件, 并关掉引脚冲突的设备树插件,并重启开发板
1 2 3 4 5 | #dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-i2c1.dtbo
#dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-touch-capacitive-goodix.dtbo
#dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-led.dtbo
dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-touch-resisitive-4wires.dtbo
|
提示
uEnv.txt文件中若没有电阻触摸相关设备树插件内容, 可通过查看/usr/lib/linux-image-4.19.35-imx6/overlays/ 路径下是否存在相关插件, 手动添加到uEnv.txt文件中。
12.2.1. 使用evtest测试电阻触摸屏¶
将电阻触摸屏设备连接到板子上的,其中电阻触摸板引脚对应关系如下
GPIO ports |
TSC function ports |
---|---|
GPIO1_IO01 |
ynlr |
GPIO1_IO02 |
ypll |
GPIO1_IO03 |
xnur |
GPIO1_IO04 |
xpul |
在终端上执行evtest命令并选择触摸屏进行测试,请根据具体输入设备选择正确设备。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | root@npi:~# evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: 20cc000.snvs:snvs-powerkey
/dev/input/event1: iMX6UL Touchscreen Controller
/dev/input/event2: sgpio-keys
Select the device event number [0-2]: 1
Input driver version is 1.0.1
Input device ID: bus 0x19 vendor 0x0 product 0x0 version 0x0
Input device name: "iMX6UL Touchscreen Controller"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 330 (BTN_TOUCH)
Event type 3 (EV_ABS)
Event code 0 (ABS_X)
Value 1662
Min 0
Max 4095
Event code 1 (ABS_Y)
Value 2052
Min 0
Max 4095
Properties:
Testing ... (interrupt to exit)
Event: time 1620379318.345195, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1620379318.345195, type 3 (EV_ABS), code 0 (ABS_X), value 3721
Event: time 1620379318.345195, type 3 (EV_ABS), code 1 (ABS_Y), value 2677
Event: time 1620379318.345195, -------------- SYN_REPORT ------------
Event: time 1620379318.381335, type 3 (EV_ABS), code 0 (ABS_X), value 3693
Event: time 1620379318.381335, type 3 (EV_ABS), code 1 (ABS_Y), value 2679
Event: time 1620379318.381335, -------------- SYN_REPORT ------------
Event: time 1620379318.417564, type 3 (EV_ABS), code 0 (ABS_X), value 3702
Event: time 1620379318.417564, type 3 (EV_ABS), code 1 (ABS_Y), value 2626
Event: time 1620379318.417564, -------------- SYN_REPORT ------------
Event: time 1620379318.453750, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0
Event: time 1620379318.453750, -------------- SYN_REPORT ------------
Event: time 1620379319.845545, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1620379319.845545, type 3 (EV_ABS), code 0 (ABS_X), value 1417
Event: time 1620379319.845545, type 3 (EV_ABS), code 1 (ABS_Y), value 1725
Event: time 1620379319.845545, -------------- SYN_REPORT ------------
Event: time 1620379319.881701, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0
Event: time 1620379319.881701, -------------- SYN_REPORT ------------
|
使用evtest获取得到的是原始的数值,需要用户自行进行坐标转换。
12.2.2. 使用libts校准电阻触摸屏¶
与电容屏不同,电阻触摸屏获取得到的是原始数据并不是坐标值,想要获取相关的坐标点需要 对原始数据进行换算,前面提到 libts是一种实用的触摸工具,能够用于触摸屏的校准,将触摸位置与屏幕显示位置统一起来。 用于也适用于电阻屏。
本小节实验也需要开启显示屏相关设备树插件,关于显示屏相关配置请移步 屏幕显示 章节。
通过以下命令下载libts-bin工具
1 | sudo apt install libts-bin
|
使用以下命令进行屏幕校准,执行以下两条命令之后,显示屏将会显示需要点击的位置, 依次点击完成后完成屏幕
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #设置环境变量,并将/dev/input/event1替换为自己的触摸屏输入设备
export TSLIB_TSDEVICE=/dev/input/event1 #此条命令建议手打
#进行屏幕校准
ts_calibrate
#终端打印消息
xres = 800, yres = 480
Took 2 samples...
Top left : X = 3819 Y = 3342
Took 1 samples...
Top right : X = 560 Y = 3290
Took 1 samples...
Bot right : X = 598 Y = 881
Took 1 samples...
Bot left : X = 3830 Y = 896
Took 1 samples...
Center : X = 2208 Y = 1948
879.625122 -0.215657 -0.002189
559.622986 0.001605 -0.156010
Calibration constants: 57647112 -14133 -143 36675452 105 -10224 65536
|
执行ts_print命令后触摸电阻屏将会打印出相对应的坐标,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #执行命令
ts_print
#打印消息
1620381220.271199: 70 97 255
1620381220.307265: 70 97 0
1620381222.189967: 409 67 255
1620381222.226232: 409 67 0
1620381223.315446: 742 66 255
1620381223.351706: 742 66 0
1620381224.468252: 741 260 255
1620381224.504461: 738 253 255
1620381224.540603: 737 249 0
1620381225.112325: 397 257 255
1620381225.148533: 397 257 0
1620381225.850632: 116 319 255
1620381225.886867: 116 319 0
|
关于libts工具使用的详细说明可参考以下链接: https://github.com/libts/tslib
12.2.3. 触摸屏相关设备树插件¶
野火imx6ull提供了很多的设备树插件源码,若想要修改电阻触摸屏设备树插件, 可参考:
其中电阻触摸屏的设备树插件为 imx-fire-touch-resisitive-4wires-overlay.dts ,源码如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include "imx6ul-pinfunc.h"
#include "imx6ull-pinfunc-snvs.h"
#include "dt-bindings/interrupt-controller/irq.h"
#include "dt-bindings/gpio/gpio.h"
/dts-v1/;
/plugin/;
/ {
fragment@0 {
target = <&iomuxc>;
__overlay__ {
pinctrl_tsc: tscgrp {
fsl,pins = <
MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xB0
MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xB0
MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xB0
MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0xB0
>;
};
};
};
fragment@1 {
target=<&tsc>;
__overlay__ {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tsc>;
xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
measure-delay-time = <0xfffff>;
pre-charge-time = <0xffff>;
touchscreen-average-samples = <32>;
status = "okay";
};
};
};
|
若想修改触摸屏控制芯片相关引脚,仅需要修改以上高亮部分代码即可。