10 触摸
1 触摸介绍
1.1 触摸屏介绍
触摸屏很早就有了,一开始是电阻触摸屏,电阻触摸屏只能单点触摸,在以前的学习机、功能机时代被广泛使用。2007年1月9日苹果发布了划时代的第一代iPhone,也就是iPhone 2G,iPhone 2G上使用了多点电容触摸屏,而当时的手机基本都是使用的电阻触摸屏。电容触摸屏优秀的触摸品质和手感瞬间征服了消费者,带来了手机触摸屏的大变革,后面新出的手机也都采用了多点电容触摸屏。
电容触摸屏与电阻触摸屏的对比:
- 多点触摸支持:电容触摸屏最大的优点是支持多点触摸(后面的电阻屏也支持多点触摸,但是为时已晚)
- 触摸灵敏度:电容屏只需要手指轻触即可,而电阻屏是需要手指给予一定的压力才有反应
- 校准需求:电容屏不需要校准,使用更便捷
如今多点电容触摸屏已经得到了广泛的应用,手机、平板、电脑、广告机等等,如果要做人机交互设备的开发,多点电容触摸屏基本是不可能绕过去的。所以本章我们就来学习一下如何使用多点触摸屏,如何获取到多点触摸值。关于电容屏的物理原理我们就不去研究了,毕竟我们不是开发电容屏的,而是电容屏的使用者,我们只需要关注如何使用电容屏,如何得到其多点触摸坐标值即可。
触摸屏的组成结构:
屏幕其实是由显示面板+触摸屏组合起来的。底下是显示面板,上面是触摸面板,将两个封装到一起就成了带有触摸屏的屏幕。电容触摸屏也是需要一个驱动IC的,驱动IC一般会提供一个I2C接口给主控制器,主控制器可以通过I2C接口来读取驱动IC里面的触摸坐标数据。
注意: M4-R1开发板搭载了一组I2C触摸接口,目前适配的驱动为gt911、FT5X06、FT5406等。与前文中来自Linux内核的驱动程序不同,该驱动为HDF框架下的驱动,用户可以在
/drivers/hdf_core/framework/model/input/driver/touchscreen/
路径下看到支持的触摸IC。
1.2 Linux下的input子系统介绍
input就是输入的意思,因此input子系统就是管理输入的子系统,是Linux内核针对某一类设备而创建的框架。比如按键输入、键盘、鼠标、触摸屏等等这些都属于输入设备,不同的输入设备所代表的含义不同,按键和键盘就是代表按键信息,鼠标和触摸屏代表坐标信息,因此在应用层的处理就不同。
input子系统架构:
- input驱动层:负责具体硬件设备的驱动实现
- input核心层:提供统一的接口和管理机制
- input事件处理层:处理和分发输入事件
最终给用户空间提供可访问的设备节点,input子系统框架如下图所示:

对于应用开发来说,我们只需要关心内核空间发送给用户空间的数据即可。
2 I2C触摸板卡接口

3 触摸屏使用---命令行方式
3.1 设备树解析
提示
下文的文件路径:out/kernel/src_tmp/linux-5.10/arch/arm64/boot/dts/rockchip/ 需要先编译码源。
下面简单的解析一下挂载在I2C1总线上的触摸屏控制器节点的描述。
注意
有两个触摸屏控制器都挂载在 SoC 的 I2C1 总线上,下文以测试屏幕搭载的汇顶科技的GT911触摸IC节点为例进行介绍.
首先是基础定义层( rk3568.dtsi ):
i2c1: i2c@fe5a0000 {
compatible = "rockchip,rk3399-i2c";
reg = <0x0 0xfe5a0000 0x0 0x1000>;
clocks = <&cru CLK_I2C1>, <&cru PCLK_I2C1>;
clock-names = "i2c", "pclk";
interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&i2c1_xfer>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
rk提供的基础定义设备树源文件中,并不提供直接的I2C触摸控制器节点描述,而是提供了I2C总线上的通用I2C控制器节点描述,原因也很简单:为了防止设备树又臭又长,这也正是我们使用设备树的初衷,下面对i2c1节点进行简单的分析。
compatible
: 指定兼容性,支持RK3399 I2C控制器reg
: 寄存器地址范围(0xfe5a0000-0xfe5a0fff)interrupts
: 中断号47,高电平触发clocks
: I2C功能时钟(CLK_I2C1)和APB时钟(PCLK_I2C1)pinctrl-0
: 默认使用i2c1_xfer引脚组status
: 默认禁用状态
下面是引脚配置层( rk3568-pinctrl.dtsi )
i2c1_xfer: i2c1-xfer {
rockchip,pins =
/* i2c1_scl */
<0 RK_PB3 1 &pcfg_pull_none_smt>,
/* i2c1_sda */
<0 RK_PB4 1 &pcfg_pull_none_smt>;
};
..............
touch_gpio: touch-gpio {
rockchip,pins =
/* 中断引脚 */
<0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>,
/* 复位引脚 */
<0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
};
以上两个节点分别是I2C1总线和触摸芯片的引脚配置节点,分别对应了I2C1的SCL和SDA引脚,以及触摸芯片的中断引脚和复位引脚。
i2c1_xfer
: I2C1总线引脚,使用GPIO0_B3作为SCL,GPIO0_B4作为SDAtouch_gpio
: 触摸芯片控制引脚,GPIO0_B5作为中断引脚(上拉),GPIO0_B6作为复位引脚
最后再看板级配置层( rk3568-toybrick.dtsi ):
&i2c1 {
status = "okay";
gt9xx: gt9xx@5d {
compatible = "goodix,gt9xx";
status = "okay";
reg = <0x5d>;
reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
touch-gpio = <&gpio0 RK_PB5 IRQ_TYPE_LEVEL_LOW>;
max-x = <7200>;
max-y = <1280>;
tp-size = <911>;
pinctrl-names = "default";
pinctrl-0 = <&touch_gpio>;
power-supply = <&vcc3v3_lcd0_n>;
};
};
该节点用于设置触摸屏的相关参数,如最大坐标、触摸点数量等,具体内容如下:
&i2c1
: 引用基础定义中的i2c1节点status = "okay"
: 使能I2C1控制器和gt9xx触摸芯片reg = <0x5d>
: gt911芯片的I2C从设备地址为0x5dreset-gpio
: 复位引脚使用GPIO0_B6,高电平有效touch-gpio
: 中断引脚使用GPIO0_B5,低电平触发max-x/max-y
: 触摸屏分辨率7200x1280tp-size = <911>
: 指定触摸芯片型号为gt911power-supply
: 电源供应来自vcc3v3_lcd0_n
3.2 应用层对触摸相关设备的测试方法
触摸屏属于input输入子系统设备,input子系统是Linux对输入设备提供的统一驱动框架。如按键、键盘、触摸屏和鼠标等输入设备的驱动方式是类似的,使用input子系统驱动的输入设备可以通过统一的数据结构提交给内核,该数据结构包括输入的时间、类型、代号以及具体的键值或坐标,内核通过 /dev/input
目录下的文件接口传递给用户空间。
getevent调试工具:
input输入子设备系统可以通过 getevent
命令来获取设备上报给系统的事件:
getevent
是一个Android/Linux系统下的调试工具- 用于监听并显示内核输入子系统产生的原始输入事件
- 可以看到最底层的、未经任何处理的硬件输入信号
板卡中内置了 getevent
命令,可以用该命令来调试触摸屏是否正常工作。
在 /dev/input
目录下,使用指令:
getevent
可以获取到所有input子设备,并监听所有设备上报事件。 事件格式解析:
返回的事件格式:设备: 类型 代码 值
事件类型表:
类型代码 | 事件类型 | 说明 |
---|---|---|
0000 | EV_SYN | 同步事件 |
0001 | EV_KEY | 按键事件 |
0003 | EV_ABS | 绝对坐标事件(触摸屏) |
事件代码表:
代码 | 名称 | 说明 |
---|---|---|
0035 | ABS_MT_POSITION_X | X坐标 |
0036 | ABS_MT_POSITION_Y | Y坐标 |
0039 | ABS_MT_TRACKING_ID | 触摸点ID |
0000 | SYN_REPORT | 报告同步 |
0002 | SYN_MT_REPORT | 多点触控报告 |
事件值说明:
值类型 | 含义 |
---|---|
坐标值 | 十六进制坐标 |
00000000 | 新触摸点开始 |
ffffffff | 触摸点结束 |
00000001 | 按键按下 |
00000000 | 按键释放 |
监听特定设备:
如果想要监听具体的子设备及其上报的事件类型,可以使用指令:
getevent -l /dev/input/event*
它会实时反馈十六进制坐标信息(x,y)和触摸点ID和同步事件,下面对事件类型和事件代码进行解释。
Linux输入事件类型:
事件类型 | 功能 | 典型应用 |
---|---|---|
EV_KEY | 按键事件 | 电源键、音量键 |
EV_ABS | 绝对坐标事件 | 触摸屏、游戏摇杆 |
EV_REL | 相对坐标事件 | 鼠标移动、滚轮 |
EV_SYN | 同步事件 | 数据帧结束标志 |
EV_MSC | 杂项事件 | 其他类型事件 |
EV_SW | 开关事件 | 盖子开合、耳机插拔 |
触摸屏常用事件代码:
代码名称 | 功能 | 说明 |
---|---|---|
ABS_MT_TRACKING_ID | 触摸点ID | 正数=新触摸,ffffffff=触摸结束 |
ABS_MT_POSITION_X | X坐标 | 触摸点横坐标 |
ABS_MT_POSITION_Y | Y坐标 | 触摸点纵坐标 |
ABS_MT_PRESSURE | 压力值 | 触摸压力大小 |
ABS_MT_TOUCH_MAJOR | 触摸面积 | 接触面积大小 |
3.3 具体功能演示
3.3.1 查看输入设备
首先进入目录 /dev/input/
,可以查看到几个输入事件:

3.3.2 识别触摸屏设备
使用指令 getevent
查看输入事件对应的输入设备:

显然,设备名为"touchscreen"的设备就是我们的触摸屏。
3.3.3 监听触摸事件
在亮屏状态下,点击屏幕,即可在终端查看到对应的触摸事件:

3.3.4 可读性更高的事件显示
我们使用可读性更高的指令 getevent -l /dev/input/event*
再次进行测试,点击屏幕后看到屏幕返回信息如下:
