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. 编写应用程序

触摸屏检测相关的应用程序与按键检测的应用程序类似,如下所示

ebf_6ull_quick_start_code/Source/input/touch_input.c
 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 ,源码如下所示

/arch/arm/boot/dts/overlays/ebf/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 ,源码如下所示

/arch/arm/boot/dts/overlays/ebf/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";
        };

    };

};

若想修改触摸屏控制芯片相关引脚,仅需要修改以上高亮部分代码即可。