电容触摸 GT911坐标定位校准—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
屏亮了还要点得准。今天配电容触摸。坐标必须按你这块屏的分辨率来,配成另一套尺寸会比完全没触摸更耗时间。
第四篇前面几章把屏点亮了。logo 能出、桌面能出,手往上一划——图标跑到别处去,或者上半屏完全点不中。这种「有触摸、但触摸是骗子」的状态,比完全没触摸更耗时间,因为你以为是显示方向的问题,会先去改横竖屏。
这章把骗子拆开。芯片是 GT911,地址 0x5d,挂在 I2C2。它不是电阻屏,也不是另一颗常见的 FT5406。开源鸿蒙标准系统上,这条通路走 HDF Input,不走内核主线 goodix 驱动。设备树里那颗 goodix,gt911 节点要保持 disabled,否则两边抢同一条总线,HDF 读寄存器全是 NACK。
我坐在板子前面时,最先做的不是改驱动,是先问三个问题:总线上到底是谁在应答?INT 脚有没有被别人拉着?报上来的 raw 坐标,是按 1024×600 报的,还是按某份公版竖屏 720×1280 报的?三个问题都有铁证,坐标那一问还出过 DisplayY = -377。负数被上层夹到 0,你就看见「上半屏失灵」。


官方这张图请盯两分钟。上面是多模输入(MMI),中间是 Input 管理器和设备抽象,下面才是芯片驱动和 I2C/GPIO 适配。GT911 的 .c 只负责「认出芯片、把点读出来」。分辨率、复位脚、中断脚、I2C 几号总线,全在 HCS 里。你改错层,编译再勤也摸不到那颗芯片。
1. 先认芯片,再谈驱动
电容屏控制器藏在屏的柔性电路上,丝印经常被排线挡住。文档写 FT5406、板上焊 GT911,这种事发生过,而且会让你在错误的 I2C 地址上排一周。
认芯片只认总线应答,不认说明书封面。
hdc shell "i2cdetect -y -r 2"
在 I2C2 上,你希望看到类似:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- 5d -- --
60: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
说明:
| 地址 | 常见身份 | 备注 |
|---|---|---|
| `0x5d` | **GT911** | 本章主角 |
| `0x38` | FT5406 / 某些温湿度 | 下一章;和 GT911 **不要同时 okay** |
| `0x36` | MIPI 相机 | 相机篇 |
| `0x60` | Type-C 口芯片 | 板载常驻,扫到很正常 |
| `UU` | 已被内核驱动占 | 不是故障 |
0x5d 没有、0x38 也没有:先查排线、供电、I2C2 有没有 okay,别先改驱动。
GT911 的产品 ID 在寄存器 0x8140,四个字节,正常是 ASCII '9','1','1',0。16 位寄存器地址,i2cget 一次搞不定,用 i2ctransfer 或下面那份 C。
hdc shell "i2ctransfer -y 2 w2@0x5d 0x81 0x40 r4"
期望类似:
0x39 0x31 0x31 0x00
0x39 0x31 0x31 就是 '9''1''1'。这是芯片身份的铁证。读失败但 i2cdetect 能扫到:多半是复位脚没释放,芯片停在下载模式,只 ACK 地址不认寄存器。
电阻屏是另一条世界:ADC 采样、XPT2046 一类,走 SPI。GT911 是电容、I2C、多点。别把电阻屏的校准程序套过来。
2. 为什么走 HDF,不走主线 goodix
内核里本来就有 drivers/input/touchscreen/goodix.c,compatible = "goodix,gt911",Linux 发行版上用得很熟。开源鸿蒙标准系统的桌面、MMI、窗口,认的是 HDF Input 报上来的点。两条栈同时 bind 同一颗芯片,结果是:
- 主线 goodix 先
i2c_request,HDF 再访问 → NACK / busy - 或者反过来,主线 probe 失败,你在
dmesg里骂 goodix,其实 HDF 已经在干活 - 两套坐标映射叠在一起,点「又像对又像不对」
所以板级设备树里,内核节点只作备查,status 保持 disabled:
&i2c2 {
status = "okay";
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&i2c2m1_xfer >911_int_pin >911_rst_pin>;
/* 内核主线 goodix:禁用,把总线让给 HDF */
gt911_lvds: gt911@5d {
compatible = "goodix,gt911";
pinctrl-names = "default";
pinctrl-0 = <>911_int_pin >911_rst_pin>;
reg = <0x5d>;
interrupt-parent = <&gpio0>;
interrupts = <RK_PC7 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio2 RK_PD0 GPIO_ACTIVE_HIGH>;
status = "disabled";
};
};
status = "disabled" 不是「这块板没有 GT911」。是「内核别 bind,HDF 来 bind」。这和 AHT20 那颗温湿度同一套路:DTS 声明地址方便对照,真正干活的人在 HCS。
内核配置里:
CONFIG_DRIVERS_HDF_TP_5P5_GT911=y
板级 build_kernel.sh 注入段要兜住它。公版碎片有时会把它关掉、把 FT5406 打开。你只改 HCS 不改这段,编出来的内核可能根本没链 GT911 芯片驱动。
对应的 pinctrl,INT 和 RST 必须是 GPIO 功能,不能停在别的复用:
mipi_panel_tp {
gt911_int_pin: gt911-int-pin {
rockchip,pins = <0 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>;
};
gt911_rst_pin: gt911-rst-pin {
rockchip,pins = <2 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
脚位(本板 LVDS / 常见 10 寸电容):
| 信号 | 引脚 | 内核编号 | 算法 |
|---|---|---|---|
| SDA/SCL | I2C2 | 总线号 2 | HCS `busNum = 2` |
| INT | GPIO0_C7 | **23** | `0*32 + 2*8 + 7` |
| RST | GPIO2_D0 | **88** | `2*32 + 3*8 + 0` |
编号算错,HCS 里写了 36、82,那是另一块屏的脚。驱动会「复位成功」(GPIO 控制器返回 0),芯片却没被碰到。
3. HCS 才是 HDF 的设备树
路径:
vendor/rk/rk3568_evb/hdf_config/khdf/input/input_config.hcs
vendor/rk/rk3568_evb/hdf_config/khdf/device_info/device_info.hcs
input_config.hcs 里和坐标、总线、脚相关的核心段如下。这是 GT911 + 1024×600 横屏 该有的样子:
root {
input_config {
touchConfig {
touch0 {
boardConfig {
match_attr = "touch_device1";
inputAttr {
inputType = 0; /* 0 = touch */
solutionX = 1024; /* 必须等于屏宽 */
solutionY = 600; /* 必须等于屏高 */
devName = "main_touch";
}
busConfig {
busType = 0; /* 0 = i2c */
busNum = 2;
}
pinConfig {
rstGpio = 88; /* GPIO2_D0 */
intGpio = 23; /* GPIO0_C7 */
rstRegCfg = [0x0, 0x0];
intRegCfg = [0x0, 0x0];
}
powerConfig {
vccType = 0; /* 硬件常供电,不用 HDF 推 LDO */
vccNum = 0;
vccValue = 1800;
vciType = 0;
vciNum = 0;
vciValue = 3300;
}
}
chipConfig {
template touchChip {
match_attr = "";
chipName = "gt911";
vendorName = "zsj";
busType = 0;
deviceAddr = 0x5D;
irqFlag = 2; /* 下降沿 */
maxSpeed = 400;
chipVersion = 0;
powerSequence {
/* [type, status, dir, delay_ms]
* type: 3=reset 4=int
* status: 0=low 1=high 2=nop
* dir: 0=in 1=out 2=nop
*/
powerOnSeq = [4, 0, 1, 5,
3, 0, 1, 10,
3, 1, 1, 60,
4, 2, 0, 50];
suspendSeq = [3, 0, 2, 10];
resumeSeq = [3, 1, 2, 10];
powerOffSeq = [3, 0, 2, 10,
1, 0, 2, 20];
}
}
chip0 :: touchChip {
match_attr = "gt911_1024x600";
chipInfo = "ZIDN45100";
chipVersion = 0;
}
}
}
}
}
}
device_info.hcs 要把芯片驱动真正挂上:
device_hdf_touch :: device {
device0 :: deviceNode {
policy = 2;
priority = 120;
preload = 0;
permission = 0660;
moduleName = "HDF_TOUCH";
serviceName = "hdf_input_event1";
deviceMatchAttr = "touch_device1";
}
}
device_touch_chip :: device {
device0 :: deviceNode {
policy = 0;
priority = 130;
preload = 0;
permission = 0660;
moduleName = "HDF_TOUCH_GT911";
serviceName = "hdf_touch_gt911_service";
deviceMatchAttr = "gt911_1024x600";
}
}
三处必须对上:
boardConfig.match_attr=device_hdf_touch的deviceMatchAttrchip0.match_attr=device_touch_chip的deviceMatchAttrmoduleName必须是HDF_TOUCH_GT911,不要留成 FT5406 那份
切过 RGB 屏的人,这里经常还停在 HDF_TOUCH_FT5406。HCS 和屏是一对,不是「一份配置打天下」。
powerOnSeq 的编码别看注释想当然。[3, 1, 0, 20] 的意思是 RST、HIGH、输入、等 20 ms——方向是输入时,写 HIGH 只进锁存器,脚根本没被驱动。GT911 上电序列要先把 INT 拉成输出、RST 拉低再拉高,最后 INT 改回输入给芯片用。
4. INT 脚被 regulator 占:probe 成功、永远没中断
公版 rk3568-evb1 一类 dtsi 里,常有:
vcc3v3_lcd0_n: vcc3v3-lcd0-n {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-boot-on;
};
GPIO0_C7 在公版 Evb 上也许真是 LCD 电源使能。在这块底板上,它是 GT911 的 INT。开机 regulator 把它拉高,大约几十秒后框架做 late cleanup,没消费者的 boot-on 电源会被关掉,脚再被拉低锁死。中断永远进不来。
你看到的现象是:ChipDetect 成功、产品 ID 是 911、main_touch 注册了,手指滑过去 dmesg 没有 IRQ。因为电平被电源框架按「使能脚」管理,不按「中断脚」管理。
修法:在板级 dts 删掉这两个属性,不要去改芯片驱动。
&vcc3v3_lcd0_n {
/delete-property/ enable-active-high;
/delete-property/ gpio;
};
同组的 vcc3v3_lcd1_n 若占了别的脚,一并删。这不是「关掉液晶供电」,电源该 always-on 的继续 always-on,只是别再用 GPIO0_C7 当使能。
验证:
hdc shell "mount -t debugfs none /sys/kernel/debug"
hdc shell "cat /sys/kernel/debug/gpio | grep -E 'gpio-23|gpio-88'"
期望 INT(23)被 HDF 申请成输入,RST(88)被申请成输出。若 23 的 label 还是某 regulator,HCS 里的 intGpio = 23 只是个数字,物理脚不听它的。
5. 坐标:720×1280 写进芯片,1024×600 拿来减
屏是横的 1024×600,桌面也修成横的了,点图标仍然不准:左半屏到不了 0,上半屏 DisplayY 是负数。方向其实对(左小于右、上小于下),坏在缩放。
HDF 通用 GT911 驱动在 CONFIG_ARCH_ROCKCHIP 分支有一份 firmWareParm[],开机写进芯片。寄存器从 0x8050 起,紧跟着的分辨率是:
/* drivers/hdf_core/framework/model/input/driver/touchscreen/touch_gt911.h */
uint8_t firmWareParm[FIRMWARE_LEN] = {
0x80, 0x50, /* 寄存器 0x8050 */
0x64, /* 配置版本 */
0xD0, 0x02, /* X = 0x02D0 = 720 */
0x00, 0x05, /* Y = 0x0500 = 1280 */
/* ... 后面一长串阈值、通道表 */
};
这是某份 720×1280 竖屏公版 的配置被照搬过来。芯片老老实实按 720×1280 报 raw。驱动 ChipVersionDefault 的 ROCKCHIP 分支若再写:
x = resX - rawX; /* resX 来自 HCS,是 1024 */
y = resY - rawY; /* resY 是 600,rawY 却能到 ~1280 */
600 - 1280 = -680,再带点边沿偏移,串口里就出现过 DisplayY: -377。上层把负数夹到 0,上半屏全部变成「点了等于点在 y=0」。左半屏 rawX 到不了 0(芯片按 720 报,还带原点偏移),减完也到不了屏幕左边。
所以:
- HCS 的 solutionX/Y 必须等于屏,这是映射的目标矩形
- 芯片实际报点范围 是另一回事,由 firmware 和模组决定
- 两者不一致时,用减法当映射,一定会穿出屏幕
实测慢划满屏(贴边缘)得到的 raw 边界,本板这一块是:
| 边 | raw |
|---|---|
| 左 | 14 |
| 右 | 597 |
| 上 | 15 |
| 下 | 1015 |
raw 随右、下增大,和屏同向,不能再做 res - raw 反转。线性标定:
#define GT_RAW_X_MIN 14
#define GT_RAW_X_MAX 597
#define GT_RAW_Y_MIN 15
#define GT_RAW_Y_MAX 1015
static void ChipVersionDefault(ChipDevice *device, FrameData *frame,
const uint8_t *buf, uint8_t pointNum)
{
for (uint8_t i = 0; i < pointNum; i++) {
int32_t resX = device->driver->boardCfg->attr.resolutionX;
int32_t resY = device->driver->boardCfg->attr.resolutionY;
int32_t rawX = (buf[GT_POINT_SIZE * i + GT_X_LOW] & 0xFF) |
((buf[GT_POINT_SIZE * i + GT_X_HIGH] & 0xFF) << 8);
int32_t rawY = (buf[GT_POINT_SIZE * i + GT_Y_LOW] & 0xFF) |
((buf[GT_POINT_SIZE * i + GT_Y_HIGH] & 0xFF) << 8);
frame->fingers[i].x = (rawX - GT_RAW_X_MIN) * resX
/ (GT_RAW_X_MAX - GT_RAW_X_MIN);
frame->fingers[i].y = (rawY - GT_RAW_Y_MIN) * resY
/ (GT_RAW_Y_MAX - GT_RAW_Y_MIN);
if (frame->fingers[i].x < 0) {
frame->fingers[i].x = 0;
} else if (frame->fingers[i].x > resX - 1) {
frame->fingers[i].x = resX - 1;
}
if (frame->fingers[i].y < 0) {
frame->fingers[i].y = 0;
} else if (frame->fingers[i].y > resY - 1) {
frame->fingers[i].y = resY - 1;
}
frame->fingers[i].valid = true;
}
}
文件:
drivers/hdf_core/framework/model/input/driver/touchscreen/touch_gt911.c
换一块模组,边界会变。标定方法:在驱动里临时打 raw 日志,手指贴四边慢划,记下最小最大,填进四个宏。轴若整体反了,对那一轴改 res - mapped,不要两轴一起翻着试。
有人问:为什么不改 firmWareParm 把 720/1280 改成 1024/600?GT911 的配置表带 checksum,写错会让芯片拒收整表,退回出厂参数,更难查。本板没有厂商提供的正确 config,所以 不改 firmware、只改主机侧映射。这是保守、可逆、上板验证过的路。
6. 改 khdf 之后,编译为什么像没改
HDF 触摸编进内核 Image(khdf),不是一个用户态 so。你改了 .c 或 .hcs,GN 的内核 action 经常 不把它们当依赖。
两口井:
口 1:源码没重编。
rm -f out/kernel/checkpoint/compile_check
rm -rf out/kernel/src_tmp/linux-5.10/boot_linux
./build.sh --product-name rk3568_evb --ccache
只跑 ninja boot_linux 有时会命中旧 Image。清 checkpoint 强迫 build_kernel.sh 再走一遍。
口 2:HCS 改了,hcb 没重生。
hc-gen 的 make 依赖常常只有顶层 hdf.hcs。你改的是被 #include 的 input_config.hcs,顶层 mtime 不变,旧的 hdf_hcs_hex.o 继续链进内核。刷完「solution 明明写了 1024,芯片还按 720 报」。
touch vendor/rk/rk3568_evb/hdf_config/khdf/hdf.hcs
# 或者删掉生成的 hdf_hcs_hex.c / .o 再编
验证新内核在跑,不要只看文件日期。驱动里留一行独特日志,刷完:
hdc shell "dmesg | grep -E 'GT911|main_touch|ChipDetect|HDF_INPUT'"
没有这些字,你刷的可能是另一块闪存上的旧 boot_linux。U-Boot 经常去 eMMC 找内核,即便你自以为在从 SD 起。刷之前:
hdc shell "cat /proc/partitions"
hdc shell "ls -l /dev/block/mmcblk*p5"
dd 必须写 /dev/block/mmcblkXp5,禁止 /dev/mmcblkXp5(不存在时会建成普通文件,md5 还对)。改了 DTS 还要刷 resource 分区 p4 里的 rk-kernel.dtb,那才是开机真正用的设备树。触摸这章如果只动了 khdf 的 .c,刷 p5 即可;动了 dts 的 pinctrl / regulator,p4 和 p5 一起刷。
7. 上板:从 dmesg 到 evtest
期望的内核日志形状(关键字,不是逐字对照):
LinuxI2cProbe: i2c adapter 2 add success
ChipDetect: TOUCH IC is GT911
Product ID : 911_....
get dev ability/attr succ
input device main_touch registered
IRQ 能挂上,/proc/interrupts 里对应 gpio 编号在手指按下时会涨。
找事件节点:
hdc shell "cat /proc/bus/input/devices"
HDF 桥过来的名字不一定叫 Goodix Capacitive TouchScreen。见过叫 main_touch,也见过叫 VSoC touchscreen——别被 VSoC 三个字母吓回去,那是桥的名字,不是「纯虚拟、没硬件」。
hdc shell "cat /proc/bus/input/devices"
# 记下 Handlers=eventN
hdc shell "evtest /dev/input/event11"
没有 evtest 就用 od:
hdc shell "od -An -tx1 /dev/input/event11"
按下应看到 EV_ABS(type=0x03)的 ABS_MT_POSITION_X/Y,以及 EV_SYN。坐标应在 [0,1023]×[0,599]。出现负数、或 Y 经常是 0,回到第 5 节。
桌面验证:点左上角状态栏、右下角导航,四角都能点中,这一章才算过。只看 dmesg 有 ChipDetect,只能说明 I2C 通,不能说明映射对。
8. 完整 C:读产品 ID,确认不是「DTS 写了就算」
用户态 32 位 musl。不要用 aarch64 的 gcc。下面这份只依赖 /dev/i2c-2,CONFIG_I2C_CHARDEV=y 时才有这个节点。
/* gt911_id.c — 读 GT911 0x8140 产品 ID
* 编译(在 OpenHarmony SDK native 目录下):
*
* armv7-unknown-linux-ohos-clang --target=arm-linux-ohos \
* --sysroot=${OHOS_NATIVE}/sysroot \
* -o gt911_id gt911_id.c \
* -Wl,--dynamic-linker=/system/lib/ld-musl-arm.so.1
*
* hdc file send gt911_id /data/gt911_id
* hdc shell "chmod 755 /data/gt911_id; /data/gt911_id"
*/
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#define GT911_ADDR 0x5d
#define GT911_REG_ID 0x8140
static int gt911_read(int fd, uint16_t reg, uint8_t *buf, uint16_t len)
{
uint8_t addr[2] = { (uint8_t)(reg >> 8), (uint8_t)(reg & 0xff) };
struct i2c_msg msgs[2] = {
{ .addr = GT911_ADDR, .flags = 0, .len = 2, .buf = addr },
{ .addr = GT911_ADDR, .flags = I2C_M_RD, .len = len, .buf = buf },
};
struct i2c_rdwr_ioctl_data xfer = { .msgs = msgs, .nmsgs = 2 };
return ioctl(fd, I2C_RDWR, &xfer);
}
int main(void)
{
int fd = open("/dev/i2c-2", O_RDWR);
if (fd < 0) {
perror("open /dev/i2c-2");
return 1;
}
uint8_t id[4] = {0};
if (gt911_read(fd, GT911_REG_ID, id, 4) < 0) {
perror("read 0x8140");
close(fd);
return 1;
}
close(fd);
printf("raw: %02x %02x %02x %02x\n", id[0], id[1], id[2], id[3]);
printf("id : %c%c%c\n", id[0], id[1], id[2]);
if (id[0] == '9' && id[1] == '1' && id[2] == '1') {
printf("PASS: GT911\n");
return 0;
}
printf("FAIL: not GT911. 若地址 0x38 有应答,去看 FT5406 那篇。\n");
return 2;
}
HDF 已经占用 0x5d 时,这份程序会报 busy,那反而是好消息:说明驱动占着芯片。先 i2cdetect 看 UU。要强制用户态读,得停 HDF 触摸(重启前的诊断才用),日常不要和驱动抢。
读报点寄存器 0x814E(buffer status)可以确认手指按下时芯片有没有置位。status 的 bit7 为 1 表示有新点。这能区分「芯片没报点」和「报了但映射错」。
/* 轮询 0x814E,按一下屏应看到非零 */
uint8_t st = 0;
if (gt911_read(fd, 0x814E, &st, 1) == 0) {
printf("status=0x%02x%s\n", st,
(st & 0x80) ? " (have touch)" : "");
}
9. 应用侧:触摸已经进 MMI,不必自己读 I2C
ArkTS 应用不要再去打开 /dev/i2c-2。点、滑、多指,走窗口的触摸事件。下面这份只用来在开发期把坐标打到屏幕上,确认「应用看到的点和手指一致」。量产界面没必要留。
// TouchProbe.ets — API 11,横屏 1024×600
import window from '@ohos.window';
@Entry
@Component
struct TouchProbe {
@State info: string = '用手指点、滑,看坐标是否落在屏内';
@State x: number = -1;
@State y: number = -1;
build() {
Column() {
Text('GT911 坐标探针').fontSize(22).fontWeight(FontWeight.Bold)
.margin({ bottom: 12 })
Text(this.info).fontSize(16).fontColor('#1565C0')
Text(`x=${this.x} y=${this.y}`).fontSize(28).margin({ top: 24 })
Text('左上应接近 (0,0),右下应接近 (1023,599)。\n出现负数或超界,回到驱动映射。')
.fontSize(14).margin({ top: 16 })
}
.width('100%').height('100%')
.justifyContent(FlexAlign.Center)
.onTouch((e: TouchEvent) => {
if (e.touches.length > 0) {
this.x = Math.round(e.touches[0].x);
this.y = Math.round(e.touches[0].y);
this.info = `pointers=${e.touches.length}`;
}
})
}
async aboutToAppear() {
try {
let w = await window.getLastWindow(getContext(this));
await w.setPreferredOrientation(window.Orientation.LANDSCAPE);
} catch (err) {
this.info = '横屏请求失败: ' + JSON.stringify(err);
}
}
}
若桌面能点中图标,这个页面只是复读。若桌面不准、这个页面准,问题在 Launcher 窗口尺寸;反过来,两边都不准,问题在 HDF 映射。分层,别两边一起改。
10. 和 FT5406、电阻屏、矩阵键盘的边界
| 东西 | 怎么区分 | 去哪一章 |
|---|---|---|
| GT911 @0x5d | I2C 产品 ID `911` | 本章 |
| FT5406 @0x38 | 常跟 RGB / 某款 MIPI 屏 | `23-电容触摸FT5406.md` |
| 电阻屏 | SPI + ADC,不是这颗 | 别套这篇 HCS |
| 板载 KEY3/4/5 | adc-keys / gpio-keys | `24-板载按键.md` |
| 4×4 矩阵 | `gpio-matrix-keypad` | `25-矩阵键盘.md` |
同一条 I2C2 上 GT911 和 FT5406 不要同时 okay。地址不同看似能共存,复位脚、中断脚、HCS 的 moduleName 只有一份。两套屏轮流接,就做两份 HCS / 两份镜像,切屏等于切触摸。
11. 排障表
| 现象 | 先看 | 原因 | 处理 |
|---|---|---|---|
| `i2cdetect` 无 0x5d | 排线、I2C2 status、供电 | 没芯片或总线没起来 | 先硬件 |
| 0x5d ACK,0x8140 NACK | RST 时序、INT 占用 | 芯片停在错误模式 | 查 powerOnSeq、regulator |
| ChipDetect 成功,无报点 | `debugfs` 看 gpio-23 | INT 被 regulator 占 | 删 `vcc3v3_lcd0_n` 的 gpio |
| 有报点,上半屏失灵 | 串口 DisplayY 是否为负 | 720×1280 映射到 600 | 改 `ChipVersionDefault` |
| 点左右反了 | raw 是否随右增大 | 多做了一次 `res-raw` | 去掉反转 |
| 改 HCS 不生效 | `hdf.hcs` mtime | include 没触发 hc-gen | `touch hdf.hcs` 重编 |
| 改 .c 不生效 | `dmesg` 无新日志 | 旧 Image / 刷错介质 | 清 checkpoint,刷 `/dev/block/` |
| 和 FT5406 谁也不稳 | 两套 moduleName | 抢总线、抢脚 | 只留一套 okay |
flowchart TD
A[触摸不准或无触摸] --> B{i2cdetect 0x5d?}
B -->|无| C[查排线 I2C2 供电]
B -->|有| D{0x8140 读到 911?}
D -->|否| E[RST/INT/时序]
D -->|是| F{dmesg ChipDetect?}
F -->|否| G[HCS moduleName / GT911=y / goodix 是否抢]
F -->|是| H{有中断计数?}
H -->|否| I[GPIO0_C7 被 regulator 占]
H -->|是| J{坐标在 0..1023 / 0..599?}
J -->|否| K[firmWareParm 720x1280 映射]
J -->|是| L[查窗口横竖屏]
芯片身份用 I2C 说话:GT911 @0x5d,产品 ID 911。说明书封面可以错,总线不会陪你错。开源鸿蒙标准系统走 HDF Input,内核 goodix 节点 disabled 是让路,不是拆掉触摸。HCS 的 solutionX/Y 是屏的像素;芯片 firmware 可能仍按 720×1280 报,用减法硬套会得到负的 DisplayY。INT = GPIO0_C7 时,公版 LCD 电源节点必须放开这根脚。改 khdf 要清 checkpoint,改 include 进去的 HCS 要碰顶层 hdf.hcs。刷 /dev/block/,动 DTS 记得 resource 分区。
同一条 I2C,另一个地址、另一套脚,是 FT5406。两套配置不要在同一份镜像里同时亮绿灯。
系列第 22 篇 · 芯片:瑞芯微 RK3568 · OpenHarmony 4.1(API 11) · Linux 5.10
更多推荐



所有评论(0)