11. input子系统:触摸屏¶
在上节内容中,已经讲解到了如何使用input输入子系统读取按键值, 触摸屏也是属于input输入子系统的设备,关于input输入子系统 的内容请参考 input子系统:按键检测
11.1. 电容触摸屏¶
11.1.1. 使能电容触摸屏相关设备树插件¶
野火IMX8M提供了很多的设备树插件,用于控制板子上外设的开启,首先我们先需要开启触摸屏相关的设备树插件。修改 /boot/uEnv.txt 文件内容, 使能触摸屏设备树相关插件内容,并且重启。
如果是20240912之前的镜像,仅支持野火5.5寸mipi屏幕,因为HDMI是通过mipi转的,开启mipi屏幕的时候需要关闭HDMI插件,然后开启触摸和mipi设备树插件:
1 2 3 4 5 6 | #注释掉HDMI设备树插件
#dtoverlay=/usr/lib/linux-image-5.4.47-imx8mm/freescale/overlays/imx8mm-fire-hdmi.dtbo
#开启触摸和mipi设备树插件
dtoverlay=/usr/lib/linux-image-5.4.47-imx8mm/freescale/overlays/imx8mm-fire-touch-capacitive-goodix.dtbo
dtoverlay=/usr/lib/linux-image-5.4.47-imx8mm/freescale/overlays/imx8mm-fire-mipi-hx8399.dtbo
|
如果是20240912及以后的镜像,支持野火5.5、7、10.1寸mipi屏幕,因为HDMI是通过mipi转的,开启mipi屏幕的时候需要关闭HDMI插件,然后开启mipi设备树插件(显示和触摸已经写到同一个设备树插件):
1 2 3 4 5 6 7 | #注释掉HDMI设备树插件
#dtoverlay=/usr/lib/linux-image-5.4.47-imx8mm/freescale/overlays/imx8mm-fire-hdmi.dtbo
#根据连接的屏幕开启以下其中一个插件,以5.5寸mipi屏幕为例
dtoverlay=/usr/lib/linux-image-5.4.47-imx8mm/freescale/overlays/imx8mm-fire-5.5-mipi-hx8399.dtbo
#dtoverlay=/usr/lib/linux-image-5.4.47-imx8mm/freescale/overlays/imx8mm-fire-7-mipi-ek79007.dtbo
#dtoverlay=/usr/lib/linux-image-5.4.47-imx8mm/freescale/overlays/imx8mm-fire-10.1-mipi-ili9881c.dtbo
|
查看 /dev/input 以及 /dev/input/by-path 目录下的内容:
1 2 3 4 5 6 7 8 9 | root@lubancat:~# ls -l /dev/input
总用量 0
drwxr-xr-x 2 root root 80 6月 18 22:55 by-path
crw-rw---- 1 root input 13, 64 6月 18 22:55 event0
crw-rw---- 1 root input 13, 65 6月 18 22:55 event1
root@lubancat:~# ls -l /dev/input/by-path/
总用量 0
lrwxrwxrwx 1 root root 9 6月 18 22:55 platform-30370000.snvs:snvs-powerkey-event -> ../event0
lrwxrwxrwx 1 root root 9 6月 18 22:55 platform-30a40000.i2c-event -> ../event1
|
从以上输出可知,event0是ONOFF按键,event1对应屏幕i2c触摸,不同板子情况可能不同。
11.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 63 64 | root@lubancat:~# evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: 30370000.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 0x38f version 0x1060
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 0
Min 0
Max 1079
Event code 1 (ABS_Y)
Value 0
Min 0
Max 1919
Event code 47 (ABS_MT_SLOT)
Value 0
Min 0
Max 4
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 1079
Event code 54 (ABS_MT_POSITION_Y)
Value 0
Min 0
Max 1919
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 1702197058.929675, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 0
Event: time 1702197058.929675, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 442
Event: time 1702197058.929675, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 1110
Event: time 1702197058.929675, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 48
Event: time 1702197058.929675, type 3 (EV_ABS), code 50 (ABS_MT_WIDTH_MAJOR), value 48
Event: time 1702197058.929675, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1702197058.929675, type 3 (EV_ABS), code 0 (ABS_X), value 442
Event: time 1702197058.929675, type 3 (EV_ABS), code 1 (ABS_Y), value 1110
Event: time 1702197058.929675, -------------- SYN_REPORT ------------
Event: time 1702197059.077347, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 444
Event: time 1702197059.077347, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 1111
Event: time 1702197059.077347, type 3 (EV_ABS), code 0 (ABS_X), value 444
Event: time 1702197059.077347, type 3 (EV_ABS), code 1 (ABS_Y), value 1111
Event: time 1702197059.077347, -------------- SYN_REPORT ------------
|
根据以上信息即可知道当触摸屏幕时有什么事件产生。
11.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;
}
|
通过以下命令在开发板上编译
1 | gcc -o touch touch.c
|
运行程序后,点击触摸屏将不断打印坐标信息。
11.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 22 | #设置环境变量,并将/dev/input/event1替换为自己的触摸输入设备
export TSLIB_TSDEVICE=/dev/input/event1 #这条命令建议手打
#进行屏幕校准
ts_calibrate
#终端打印消息
root@lubancat:/# ts_calibrate
xres = 1080, yres = 1920
Took 1 samples...
Top left : X = 44 Y = 43
Took 1 samples...
Top right : X = 1060 Y = 54
Took 1 samples...
Bot right : X = 1057 Y = 1896
Took 1 samples...
Bot left : X = 15 Y = 1898
Took 1 samples...
Center : X = 560 Y = 964
11.004611 0.952012 0.008295
6.290519 -0.004122 0.984516
Calibration constants: 721198 62391 543 412255 -270 64521 65536
|
提示
重新执行ts_calibrate能够对屏幕进行再次校准。
执行ts_print命令后触摸触摸屏将会打印出相对应的坐标,如下所示
1 2 3 4 5 6 7 8 9 10 11 | root@lubancat:/# ts_print
1702256579.519596: 533 1450 255
1702256579.699112: 533 1450 0
1702256580.806891: 292 1144 255
1702256581.156257: 292 1144 0
1702256582.008168: 236 1662 255
1702256582.633285: 236 1662 0
1702256583.238694: 626 1044 255
1702256583.367507: 626 1044 0
1702256583.867282: 537 1619 255
1702256583.950065: 537 1619 0
|
关于libts工具使用的详细说明可参考以下链接: https://github.com/libts/tslib
11.1.5. 触摸屏相关设备树插件¶
野火IMX8M提供了很多的设备树插件源码,若想要修改触摸屏设备树插件, 可参考:
其中触摸屏的设备树插件为 imx8mm-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 54 55 | /dts-v1/;
/plugin/;
#include "../imx8mm-pinfunc.h"
#include "dt-bindings/gpio/gpio.h"
#include "dt-bindings/interrupt-controller/arm-gic.h"
/ {
fragment@0 {
target = <&i2c3>;
__overlay__ {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>;
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
gtxx_tsc@5d {
compatible = "goodix,gt911";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tsc>;
reg = <0x5d>;
status = "okay";
reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
irq-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
interrupt-parent = <&gpio1>;
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
touchscreen-inverted-x = <1>;
touchscreen-inverted-y = <1>;
};
};
};
fragment@1 {
target= <&iomuxc>;
__overlay__{
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA 0x400001c3
>;
};
pinctrl_tsc: tscgrp {
fsl,pins = <
MX8MM_IOMUXC_SAI5_RXD2_GPIO3_IO23 0x149
MX8MM_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x1d6
>;
};
};
};
};
|
若想修改触摸屏控制芯片相关引脚,仅需要修改以上高亮部分代码即可。