时间:2022-05-30 09:38
人气:
作者:admin
上篇文章介绍了LCD屏幕的使用,这个屏幕还有触摸功能,本篇就来介绍LCD的触摸功能的使用。
关于触摸的内容有点多,分为上下两篇进行讲解,本篇先介绍触摸驱动的编写以及将触摸点坐标实时打印出来进行测试,先有一个整体的使用感受,下篇文章再介绍具体的触摸上报协议以及图形化的测试方法。
LCD的触摸功能,本质就是显示屏上再叠加一层透明的触摸屏,实现触摸的方式与LCD进行交互。
触摸屏分为电阻触摸屏和电容触摸屏。
电阻触摸屏是一种传感器,其结构是薄膜加上玻璃的结构,两结构相邻的一面上均涂有ITO(一种导电性和透明性很好的)涂层。当触摸操作时,两层结构挤压接触,经由感应器传出相应的电信号,通过运算转化为屏幕上的X、Y值。
电容技术触摸屏CTP(Capacity Touch Panel)是利用人体的电流感应进行工作的。电容屏是一块四层复合玻璃屏,电容式触摸屏就是支持多点触摸的人机交互方式,普通电阻式触摸屏只能进行单一点的触控。
本篇使用的是野火的7寸电容触摸屏,分辨率和屏幕一样,800x480。触摸驱动芯片我GT911,是IIC接口的芯片。

触摸芯片有四个引脚:
SDA:触摸芯片的IIC 通信引脚
SCL:触摸芯片的IIC 通信引脚
RSTN:触摸芯片的复位引脚
INT:触摸芯片的中断引脚
对应板子原理图的触摸接口如下:

对应屏幕原理图的触摸接口如下:

触摸芯片用到IIC通信,还要用到复位引脚和中断引脚,因此需要先在设备树中对引脚信息进行配置。
修改imx6ull_myboard.dts文件。
在设备树中把触摸要用到的引脚追加到 iomuxc即可。
| 引脚 | 功能 |
|---|---|
| UART4_RX_DATA | 复用为 I2C1_SDA,用作 IIC1 的 SDA 引脚 |
| UART4_TX_DATA | 复用为 I2C1_SCL,用作 IIC1 的 SCL 引脚 |
| LCD_RST | 复用为 GPIO3_IO04 用作触摸芯片的复位引脚 |
| SNVS_TAMPER9 | 复用为 GPIO5_IO09 用作触摸芯片的 irq 引脚,接收触摸中断 |
需要注意的是,SNVS_TAMPER9 引脚被复用为 GPIO5_IO09,需要追加到 iomuxc_snvs 节点。
触摸芯片用到的是IIC1,这两个引脚在设备树中以及默认添加了,无需修改:

&iomuxc节点中添加:
/*my gt911*/
pinctrl_tsc_reset: tscresetgrp {
fsl,pins = <
/* used for tsc reset */
MX6UL_PAD_LCD_RESET__GPIO3_IO04 0x10b0
>;
};

&iomuxc_snvs节点中添加:
/*my gt911*/
pinctrl_tsc_irq: tsc_irq {
fsl,pins = <
/* used for tsc irq */
MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x4001b8b0
>;
}

GT911触摸驱动作为一个IIC设备挂载在IIC1总线上,找到IIC1节点:

需要在 IIC1 设备节点下追加相应的子节点:
gt911_tsc@5d {
compatible = "goodix,gt911";
reg = <0x5d>;
pinctrl-0 = <&pinctrl_tsc_reset>;
pinctrl-1 = <&pinctrl_tsc_irq>;
reset-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>;
irq-gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>;
interrupt-parent = <&gpio5>;
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
};
修改后:

reg = <0x5d>是GT911触摸芯片在 IIC1总线上的地址。
查看GT911的数据手册,找到寄存器相关的表格:

主要关注以下这些寄存器,它们是用来读取触摸坐标点的:
| Addr | Access | bit7~bit0 |
|---|---|---|
| 0x814E | R/W | buffer status(7) large detect(6) Reserved(5~4) number of touch points(3~0) |
| 0x814F | R | track id |
| 0x8150 | R | point 1 x coordinate (low byte) |
| 0x8151 | R | point 1 x coordinate (high byte) |
| 0x8152 | R | point 1 y coordinate (low byte) |
| 0x8153 | R | point 1 y coorte (high byte) |
| 0x8154 | R | Point 1 size (low byte) |
| 0x8155 | R | Point 1 size (high byte) |
| 0x8156 | R | Reserved |
| 0x8157 | R | track id |
| ... | ... | ... |
| 0x815F | R | track id |
| ... | ... | ... |
| 0x8167 | R | track id |
| ... | ... | ... |
| 0x816F | R | track id |
| 0x8170 | R | point 5 x coordinate (low byte) |
| 0x8171 | R | point 5 x coordinate (high byte) |
| 0x8172 | R | point 5 y coordinate (low byte) |
| 0x8173 | R | point 5 y coordinate (high byte) |
| 0x8174 | R | Point 5 size (low byte) |
| 0x8175 | R | Point 5 size (high byte) |
| 0x8176 | R | Reserved |
0x814E:这个寄存器很重要,它是可读可写的寄存器,通过读取该寄存器,可以知道当前是否有触摸点(由最高位表示),以及有几个触摸点(由低3位表示)
0x814F~0x8156:是第一组触摸的坐标数据
0x814F:是触摸点的追踪id,GT911支持5点触摸,这里id的取值为0~4
0x8150:触摸点1的x坐标(低字节)
0x8151:触摸点1的x坐标(高字节)y
0x8152:触摸点1的y坐标(低字节)
0x8153:触摸点1的y坐标(高字节)
0x8154~0x8156:暂不使用
0x8157以后的寄存器:与第一组触摸的坐标数据的含义类似,一个有五组
注:GT911支持硬件追踪触摸点,因此为每个触摸点提供了一个track id,举个简单的例子,当5个手指依次触摸到屏幕时,5组坐标寄存器中的track id会依次是0、1、2、3、4,当松开第1个手指时,即track id为0的点没有了,此时5组坐标寄存器,是只有前45组坐标寄存器有数据,track id会依次是1、2、3、4(理解这个很重要,因为我一开始想当然的误认为,移开第1个手指时,是第1组坐标寄存器没数据了)
新建gt911.c文件作为驱动文件
触摸芯片GT911的使用,本质是使用IIC通信,进行数据的读写,因为触摸屏的驱动,实际就是IIC驱动。另外,触摸的数据是通过中断的方式触发的,因此触摸驱动的编写,涉及到中断的处理。在中断时,读取到触摸数据后,要传递到应用层,这里是使用Linux的input子系统(这也是Linux的一种软件分层设计的方式)。
所以,编写触摸驱动,主要涉及3点:
IIC协议的驱动
中断的处理(获取触摸数据)
input子系统(将触摸数据传递到应用层)
GT911的驱动按照IIC驱动来写,当驱动运行时,会自动运行gt911_probe,在这个函数中会进行各种初始化操作。另外注意匹配列表,这里的“goodix,gt911”对应设备树中添加的设备节点,两处的名字要一致。
/* 匹配列表 */
static const struct of_device_id gt911_of_match[] = {
{.compatible = "goodix,gt911"},
{/* Sentinel *