ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

GT911触摸调试全解析:从I2C通信到tslib校准的嵌入式实战

GT911触摸调试全解析:从I2C通信到tslib校准的嵌入式实战 1. 为什么GT911值得单独写一篇调试实录GT911这颗触摸控制器在嵌入式圈子里出镜率极高7寸、10.1寸的电容屏模组上经常能看到它的身影。它支持最多5点触控I2C接口自带中断引脚性价比高供货也相对稳定。但真正上手调过的人都知道这颗芯片的坑并不少——上电时序、I2C地址切换、中断触发方式、坐标轴方向、固件配置区每一项都可能让你在示波器和逻辑分析仪前面坐一整个下午。这篇实录面向的是正在RK3568、RK3399、全志H3/H6这类主流平台上调试GT911的嵌入式工程师也适合刚接触Linux输入子系统、想搞清楚设备树和tslib到底在干什么的开发者。我会从硬件上电那一刻讲起把设备树配置、驱动匹配、I2C通信验证、中断调试、坐标校准这一整条链路拆开揉碎把我在实际项目中踩过的坑和验证过的参数都摆出来。你如果正对着一个触摸没反应或者坐标乱飞的屏幕发愁这篇内容应该能帮你省下不少时间。需要提前说明的是不同SoC平台的设备树语法和引脚定义差异较大我会以RK3568为主轴展开其他平台在关键差异处会单独标注。所有I2C地址、寄存器值、时序参数都来自实际调试记录你可以直接拿去对照自己的硬件。2. 硬件链路与上电时序触摸不工作的第一嫌疑人2.1 GT911的引脚定义与供电要求GT911的封装通常是24pin的QFN核心引脚包括VDD模拟供电典型3.3V、VDDIOIO供电1.8V或3.3V、RESET、INT、SDA、SCL以及几个地址选择引脚。这里第一个容易翻车的地方就是VDDIO的电压选择——它必须和主控I2C总线的电平匹配。RK3568的I2C控制器默认是3.3V电平如果你买的屏模组上VDDIO被硬件拉到了1.8V而你没有做电平转换I2C通信就会时好时坏甚至完全无应答。我在一个项目里遇到过这样的情况屏幕厂给的规格书写着VDDIO支持1.8V到3.3V模组上默认焊的是1.8V。上电后I2C扫描能偶尔看到0x5D的地址但读寄存器全是0xFF。后来把VDDIO改到3.3V通信立刻稳定。所以拿到模组第一件事用万用表量一下VDDIO的实际电压别只看规格书。供电时序方面GT911要求VDD先上电然后VDDIO最后拉高RESET。虽然很多模组内部有RC延时实际不严格按这个顺序也能工作但如果你的板子上电后触摸完全没反应优先检查RESET引脚是否被正确拉高。有些模组把RESET直接接到了VDDIO上靠上电自动复位这种设计反而容易出问题——因为RESET的下降沿需要足够宽才能触发芯片复位如果电源上升沿太慢芯片可能进入不确定状态。2.2 I2C地址选择与上电时序的配合GT911支持两个I2C从地址0x5D和0x14。地址的选择不是靠硬件跳线而是在RESET上升沿期间由INT引脚的电平决定的。具体来说当RESET从低变高时如果INT为低地址是0x5D如果INT为高地址是0x14。这个机制意味着INT引脚在复位阶段不能随便被外部电路拉死否则地址就固定了。实际调试中我建议在设备树里先按0x5D配置因为绝大多数模组默认走这个地址。如果I2C扫描不到设备再尝试0x14。用i2cdetect工具扫描的时候要注意GT911在未初始化时可能不会立即响应需要先确保RESET时序正确。注意有些模组的INT引脚上拉了10K电阻到VDDIO这会导致复位时INT为高地址变成0x14。如果你按0x5D配置死活不通先量一下INT引脚在复位期间的电平。2.3 中断引脚的触发方式选择GT911的INT引脚是中断输出支持电平触发和边沿触发。在Linux驱动中通常配置为下降沿触发或低电平触发。我个人的经验是优先用下降沿触发因为电平触发在中断服务程序处理不及时的情况下容易反复进入中断导致CPU占用率飙升。但这里有个细节GT911在检测到触摸后会拉低INT直到主机读取完坐标数据后才释放。如果你配置成下降沿触发每次触摸只会触发一次中断驱动读取数据后INT恢复高电平下一次触摸再触发。这个模式最干净。如果配置成低电平触发驱动必须在中断处理中确保读完所有数据否则INT一直为低中断会持续触发。在设备树中中断配置通常写成这样gt911: touchscreen5d { compatible goodix,gt911; reg 0x5d; interrupt-parent gpio3; interrupts RK_PB0 IRQ_TYPE_EDGE_FALLING; irq-gpios gpio3 RK_PB0 GPIO_ACTIVE_HIGH; reset-gpios gpio3 RK_PB1 GPIO_ACTIVE_HIGH; VDDIO-supply vcc_3v3; };这里的IRQ_TYPE_EDGE_FALLING就是下降沿触发。irq-gpios和reset-gpios的GPIO_ACTIVE_HIGH表示高电平有效具体要根据你的硬件设计来定。有些板子用低电平复位那就得改成GPIO_ACTIVE_LOW。3. 设备树配置从引脚定义到驱动匹配3.1 RK3568平台下的I2C节点配置RK3568的设备树结构比较清晰I2C控制器挂在AMBA总线上每个控制器下面可以挂多个设备。GT911通常接在I2C1或I2C3上具体看硬件原理图。配置的时候首先要确保I2C控制器本身被使能并且引脚复用正确。i2c1 { status okay; clock-frequency 400000; pinctrl-names default; pinctrl-0 i2c1m0_xfer; gt911: touchscreen5d { compatible goodix,gt911; reg 0x5d; interrupt-parent gpio3; interrupts RK_PB0 IRQ_TYPE_EDGE_FALLING; irq-gpios gpio3 RK_PB0 GPIO_ACTIVE_HIGH; reset-gpios gpio3 RK_PB1 GPIO_ACTIVE_HIGH; VDDIO-supply vcc_3v3; touchscreen-size-x 1024; touchscreen-size-y 600; touchscreen-inverted-x; touchscreen-swapped-x-y; }; };clock-frequency设成400K是GT911支持的标准速率也可以降到100K提高稳定性。pinctrl-0引用的i2c1m0_xfer是RK3568的I2C1引脚复用组具体用m0还是m1要看你的引脚分配。touchscreen-size-x和touchscreen-size-y定义的是触摸区域的分辨率必须和屏幕的实际分辨率一致。如果这里填错了触摸坐标会按比例缩放导致点击位置偏移。touchscreen-inverted-x和touchscreen-swapped-x-y这两个属性用来调整坐标轴方向后面校准部分会详细讲。3.2 驱动匹配与compatible字符串的坑GT911在Linux内核中有两个驱动一个是老式的goodix驱动一个是新的goodix_ts驱动。compatible字符串决定了哪个驱动会匹配。常见的有goodix,gt911、goodix,gt9110、goodix,gt9xx等。如果你写的compatible字符串和驱动里定义的不一致设备树节点会被忽略驱动根本不会probe。我遇到过最典型的问题是内核里编译的是goodix_ts驱动它支持的compatible是goodix,gt911但设备树里写的是goodix,gt9xx结果驱动加载了但probe失败dmesg里只有一句goodix_ts: probe of 1-005d failed with error -22。这种错误码-22是EINVAL通常意味着驱动在解析设备树属性时发现了不合法或缺失的字段。排查方法很简单去内核源码的drivers/input/touchscreen/目录下找到对应的驱动文件看它的of_device_id表里列了哪些compatible字符串设备树里必须完全匹配其中一个。另外有些驱动还要求必须提供irq-gpios和reset-gpios缺一个就会probe失败。3.3 引脚复用与GPIO冲突排查RK3568的引脚复用非常灵活一个物理引脚可以配置成GPIO、I2C、SPI、UART等多种功能。如果你在设备树里把某个引脚配成了GPIO但pinctrl里又把它复用成了I2C就会产生冲突。表现是I2C通信时有时无或者GPIO控制完全无效。排查这类问题我通常用以下步骤确认原理图上GT911的INT和RESET接的是哪几个GPIO。在RK3568的TRM手册里查这些GPIO的默认复用功能。检查设备树中是否有其他节点占用了这些引脚。用cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins查看引脚的当前复用状态。如果发现引脚被其他驱动占用需要在该驱动节点里把status改成disabled或者调整引脚分配。提示RK3568的GPIO3_B0和GPIO3_B1经常被默认复用为其他功能使用前务必在pinctrl中显式配置为GPIO模式。4. I2C通信验证与固件配置区解析4.1 用i2c-tools确认设备在线设备树配置好、驱动加载后第一步是确认I2C总线上能看到GT911。用i2cdetect扫描i2cdetect -y 1如果看到0x5D或0x14被标记为UU说明设备已经被驱动占用如果是0x5D但没有UU说明设备在线但驱动没绑定。如果什么都没看到那就是硬件或时序问题。有时候i2cdetect会显示地址但读寄存器失败这通常是I2C电平不匹配或上拉电阻不合适。GT911的I2C总线需要4.7K到10K的上拉电阻如果模组上没有或者阻值太大通信会不稳定。我习惯在调试时用示波器看SDA和SCL的波形确认上升沿是否足够陡峭。4.2 GT911的配置区与固件参数GT911内部有一块配置区地址从0x8047开始长度184字节。这块区域存储了触摸屏的分辨率、触发阈值、坐标轴方向、中断模式等参数。驱动在probe的时候会读取配置区如果发现配置和设备树不一致会尝试写入新的配置。配置区的关键字段包括偏移地址字段名说明0x8047Config_Version配置版本号0x8048X_Output_MaxX轴最大坐标0x804AY_Output_MaxY轴最大坐标0x804CTouch_Number支持的最大触点数0x8050Module_Switch1坐标轴交换和翻转控制0x8051Module_Switch2中断触发方式等0x8056Refresh_Rate报点率Module_Switch1的bit0控制X轴翻转bit1控制Y轴翻转bit2控制X/Y交换。这些位的组合决定了触摸坐标的方向。如果你发现触摸方向不对不一定非要改设备树的touchscreen-inverted-x也可以直接改配置区。但改配置区需要驱动支持有些驱动在probe时会覆盖配置区所以设备树的方式更可靠。4.3 中断调试从request_irq到实际触发中断不触发是GT911调试中最常见的问题之一。驱动probe成功、I2C能读到设备ID但触摸屏幕没有任何反应dmesg里也看不到中断计数增加。这时候要按以下顺序排查首先确认INT引脚在触摸时是否有电平变化。用万用表或示波器量INT引脚正常情况下不触摸时是高电平触摸时会被拉低。如果INT始终是高电平说明GT911没有检测到触摸可能是配置区的Touch_Number设成了0或者触摸面板和芯片之间的连接有问题。如果INT有变化但驱动没反应检查设备树里的interrupts属性是否正确。RK3568的GPIO中断号需要通过irq-gpios和interrupts配合指定。有些开发者只写了irq-gpios忘了写interrupts驱动会request_irq失败。还有一种情况是中断触发了但驱动读不到数据。这通常是I2C通信在中断上下文里出了问题。GT911的中断服务程序需要通过I2C读取坐标寄存器如果I2C控制器不支持原子上下文传输就会失败。解决办法是在驱动里用工作队列把I2C读取放到进程上下文或者确认I2C控制器驱动支持中断上下文传输。5. tslib校准从原始坐标到屏幕坐标的映射5.1 tslib的编译与部署tslib是一个老牌的触摸屏校准库虽然现在很多系统用libinput代替了它但在嵌入式Qt和传统Linux GUI中仍然广泛使用。编译tslib比较简单./autogen.sh ./configure --hostarm-linux-gnueabihf --prefix/usr/local/tslib make make install部署到目标板后需要设置环境变量export TSLIB_TSDEVICE/dev/input/event2 export TSLIB_CALIBFILE/etc/pointercal export TSLIB_CONFFILE/usr/local/tslib/etc/ts.conf export TSLIB_PLUGINDIR/usr/local/tslib/lib/ts export LD_LIBRARY_PATH/usr/local/tslib/lib:$LD_LIBRARY_PATHTSLIB_TSDEVICE要指向GT911对应的event设备可以用cat /proc/bus/input/devices查看。TSLIB_CALIBFILE是校准文件的路径第一次校准前这个文件不存在ts_calibrate会自动创建。5.2 ts_calibrate的校准流程与原理运行ts_calibrate后屏幕上会出现五个十字光标依次点击后生成校准文件。这个过程的数学原理是触摸屏上报的是原始ADC坐标屏幕显示的是像素坐标两者之间是一个线性变换关系。tslib通过采集五个点的原始坐标和屏幕坐标用最小二乘法拟合出变换矩阵。校准文件pointercal里存储的就是这个矩阵的系数通常是7个整数。tslib在运行时用这些系数把原始坐标转换成屏幕坐标。如果校准后触摸仍然偏移可能是以下原因校准时光标点击不准导致拟合误差大。屏幕分辨率变了但校准文件没更新。GT911的配置区里X_Output_Max和Y_Output_Max和实际分辨率不匹配。我通常会在校准前先确认GT911上报的原始坐标范围。用evtest工具可以看到原始坐标evtest /dev/input/event2触摸屏幕的四个角记录原始坐标的最小值和最大值。如果这个范围和屏幕分辨率差异很大说明配置区需要调整。5.3 坐标轴方向调整的三种方法触摸方向不对是新手最容易慌的问题。比如你点屏幕左上角光标跑到右下角。这通常是X轴或Y轴需要翻转或者X/Y需要交换。调整方法有三种第一种是改设备树的touchscreen-inverted-x、touchscreen-inverted-y、touchscreen-swapped-x-y属性。这是最推荐的方式因为它在驱动层就完成了坐标变换上层应用不需要做任何处理。第二种是改GT911配置区的Module_Switch1寄存器。这种方式需要驱动支持配置区写入而且不同版本的GT911固件可能行为不一致。第三种是在tslib的ts.conf里加载invert插件。这种方式只影响tslib不影响其他输入子系统用户。我个人的优先级是设备树 配置区 tslib插件。设备树的方式最干净配置区的方式最底层tslib插件的方式最灵活但只对tslib生效。6. 常见问题速查与独家避坑经验6.1 触摸无反应的问题排查表现象可能原因排查方法i2cdetect扫不到设备供电异常、RESET时序不对、I2C地址错误量VDD/VDDIO电压查RESET波形试0x14地址扫到设备但驱动不probecompatible不匹配、缺少必需属性查驱动of_device_id表补全irq-gpios驱动probe成功但无中断INT引脚配置错误、中断触发方式不对量INT电平变化改IRQ_TYPE_EDGE_FALLING有中断但无坐标上报I2C读取失败、配置区未初始化查dmesg I2C错误读0x8047配置区坐标偏移或方向错误分辨率不匹配、坐标轴未调整改touchscreen-size-x/y加inverted属性触摸断断续续I2C上拉电阻不合适、电源纹波大换4.7K上拉加滤波电容6.2 上电时序的实测经验我在多个项目里总结出一个稳定的上电时序方案VDD和VDDIO同时上电延时10ms然后RESET拉低至少10ms再拉高延时50ms后开始I2C通信。这个时序在RK3568和全志H6上都验证过没有出现过初始化失败。有些模组厂会在规格书里写RESET低电平持续时间最小1ms但实际测试发现1ms太短芯片可能还没完成内部复位。我一般用10ms留足余量。另外RESET拉高后不要立即发I2C命令GT911需要大约50ms来加载配置区这段时间内I2C可能无应答。6.3 多点触控的配置要点GT911支持最多5点触控但默认配置可能只开了1点或2点。要启用多点需要改配置区的Touch_Number字段。在设备树里有些驱动支持通过goodix,no-config属性跳过配置区写入这时候就需要手动确保配置区里的Touch_Number正确。另外多点触控上报需要输入子系统支持MT协议。检查/dev/input/eventX的capabilitiesevtest /dev/input/event2如果看到ABS_MT_POSITION_X和ABS_MT_POSITION_Y说明MT协议已启用。如果没有可能是驱动版本太老需要更新内核或打补丁。6.4 校准后仍偏移的隐藏原因有一次我校准了五遍触摸还是偏最后发现是屏幕的物理边框和显示区域不重合。GT911的触摸区域覆盖了整个玻璃面板但LCD的显示区域比玻璃小一圈导致触摸坐标和显示坐标有一个固定的偏移量。这种情况在tslib里没法完全校准因为线性变换无法补偿固定偏移。解决办法是在应用层做偏移补偿或者换用支持边缘补偿的驱动。有些GT911驱动支持touchscreen-fuzz-x和touchscreen-fuzz-y属性可以设置一个死区但这不是真正的偏移补偿。最彻底的办法是找屏幕厂要触摸区域和显示区域的精确尺寸然后在配置区里调整X_Output_Max和Y_Output_Max。6.5 内核日志的阅读技巧GT911驱动在probe和运行时会输出大量日志学会看这些日志能快速定位问题。关键日志包括Goodix-TS 1-005d: ID 911, version: 1060驱动识别到芯片版本号正常。Goodix-TS 1-005d: Invalid config, using defaults配置区读取失败驱动用了默认配置。Goodix-TS 1-005d: Request IRQ failed中断申请失败检查设备树interrupts。Goodix-TS 1-005d: I2C transfer failedI2C通信错误检查硬件连接。如果日志级别不够可以在驱动里加printk或者用dynamic debugecho file goodix* p /sys/kernel/debug/dynamic_debug/control这个命令会打开goodix驱动的所有调试日志对排查问题非常有帮助。7. 从调试到量产稳定性验证与参数固化调试通过只是第一步量产阶段还要考虑一致性和稳定性。我通常会在小批量试产时做以下验证首先是高低温测试。GT911在-20°C到70°C范围内工作但触摸灵敏度会随温度变化。如果发现低温下触摸不灵可能需要调整配置区的Touch_Threshold。这个字段控制触摸检测的灵敏度值越小越灵敏但太小会导致误触。其次是电源纹波测试。GT911对电源纹波比较敏感尤其是VDDIO。如果纹波超过50mVI2C通信可能出错。在电源引脚附近加一个1uF和0.1uF的电容通常能解决。最后是ESD测试。触摸屏是人体直接接触的部件ESD防护很重要。GT911的INT和RESET引脚上建议加TVS管I2C线上可以加共模电感。如果ESD测试不过优先检查这些防护器件。参数固化方面我习惯把最终的设备树配置和tslib校准文件一起打包到固件里。校准文件可以在产线上用ts_calibrate生成后写入也可以根据屏幕批次预先计算。如果屏幕批次一致性很好甚至可以跳过产线校准直接用调试阶段的校准文件。提示量产时建议在uboot或kernel启动阶段加一个GPIO自检确认GT911的RESET和INT引脚没有被短路或虚焊。这个自检只需要拉高拉低GPIO并读回电平成本极低但能拦住大部分硬件不良。8. 写在最后的一点个人体会GT911这颗芯片说难不难说简单也不简单。它的 datasheet 写得不算详细很多关键信息要靠实测和社区经验来补。我调试过的项目里最耗时的往往不是驱动本身而是硬件上的小问题——一个上拉电阻没焊、一个电源电压不对、一个RESET时序差了10ms。所以我的建议是遇到问题先别急着改代码拿万用表和示波器把硬件链路从头到尾量一遍确认供电、时序、电平都对了再去看软件。另外设备树配置和tslib校准这两块看起来是独立的实际上关联很紧。设备树里的touchscreen-size-x/y决定了驱动上报的坐标范围tslib的校准文件又基于这个范围做变换。如果设备树里的分辨率填错了tslib怎么校准都是偏的。所以调试顺序应该是先确认I2C通信正常再确认中断触发正常然后确认原始坐标范围正确最后才做tslib校准。这个顺序能帮你少走很多弯路。
返回列表