1. 课程导入

做触摸屏驱动移植,第一件事不是翻芯片手册,而是搞清楚你手上这块屏到底是什么原理。我见过不少工程师上来就调 I2C 时序,调了半天发现屏根本不响应——后来一查,人家用的是 SPI 接口。嗯,这种坑踩过一次就记住了。

这一章我们先把基础打牢。电阻屏和电容屏的区别、常见的接口协议、还有那些绕不开的关键参数,我都会结合项目里的实际经验来讲。你想想看,驱动移植说白了就是让内核和硬件对上话,你不懂硬件怎么说话,代码写得再漂亮也没用。

1.1 电阻屏与电容屏:原理与实战选择

先说说电阻屏。它的结构其实很简单——两层透明的导电薄膜,中间用微小的绝缘点隔开。你用手指或者笔按下去,上层薄膜就会和下层接触,形成一个分压电路。控制器检测到这个电压变化,就能算出触摸点的位置。

核心要点:电阻屏只检测压力,不关心你用什么物体。戴手套、用笔、甚至用信用卡都能操作。但缺点也很明显——只能支持单点触摸,不支持多点手势。

我在一个工业平板项目里用过电阻屏。客户要求操作工必须戴手套,而且现场有油污。电容屏根本没法用,电阻屏反而成了唯一选择。那会儿我调驱动时发现,电阻屏的校准特别重要,因为每块屏的导电薄膜均匀性都不一样,不做校准的话,点击偏差能到十几个像素。

电容屏就不一样了。它利用的是人体电场和屏幕表面电极之间的耦合效应。你的手指靠近屏幕时,会改变电极间的电容值,控制器通过扫描这些电容变化来定位触摸点。

对比项 电阻屏 电容屏
感应原理 压力接触 电容耦合
多点触摸 不支持(单点) 支持(2~10点)
透光率 约 70%~80% 约 90% 以上
耐用性 易磨损,寿命约 100 万次点击 无磨损,寿命长
环境适应性 耐油污、耐水、可戴手套 怕水、怕油、裸手操作
成本 低 中高

电容屏驱动移植时,我最头疼的是噪声处理。尤其是那些廉价的电容屏控制器,在强电磁干扰环境下会疯狂报点。我曾经在一个项目里,设备旁边就是大功率电机,电容屏的触摸数据全是乱跳的。后来我在驱动里加了滤波算法,才把这个问题压下去。

1.2 触摸屏接口协议:I2C、SPI、USB

触摸屏和主控芯片之间怎么通信?目前主流的就是三种协议:I2C、SPI 和 USB。每种协议都有自己的脾气,选错了够你折腾好几天。

1.2.1 I2C 接口

I2C 是触摸屏用得最多的接口。两根线(SCL 时钟、SDA 数据),支持多设备挂载,速度一般在 100kHz~400kHz。我个人习惯优先选 I2C,因为它的驱动框架在 Linux 内核里最成熟,移植起来最省事。

我的经验:I2C 触摸屏的地址通常是 0x38~0x3C 之间。如果你发现 i2cdetect 扫不到设备,先检查上拉电阻——很多开发板为了省成本,I2C 上拉电阻没焊或者焊错了阻值。

I2C 的典型时序是这样的:主机发送起始信号 → 发送设备地址 + 写位 → 等待 ACK → 发送寄存器地址 → 等待 ACK → 发送起始信号 → 发送设备地址 + 读位 → 读取数据 → 发送停止信号。驱动里你不需要自己拼这些时序,内核的 I2C 核心层已经封装好了,你只需要调用 i2c_smbus_read_byte_data() 这类函数就行。

// I2C 触摸屏读取示例(伪代码)
struct i2c_client *client = priv->client;
u8 reg = 0x02;  // 触摸状态寄存器
s32 status = i2c_smbus_read_byte_data(client, reg);
if (status & 0x80) {
    // 触摸按下
    x = i2c_smbus_read_byte_data(client, 0x03);
    y = i2c_smbus_read_byte_data(client, 0x05);
}

1.2.2 SPI 接口

SPI 比 I2C 快得多,适合需要高刷新率的触摸屏。四根线(MOSI、MISO、SCLK、CS),全双工通信。我一般在需要多点触摸且刷新率超过 100Hz 的场景下才会选 SPI。

但 SPI 有个坑——片选信号的处理。有些触摸屏控制器要求 CS 在每次传输结束后必须拉高,否则会进入错误状态。我曾经调试一块 SPI 触摸屏,死活读不到数据,最后用示波器一看,CS 信号一直低着,控制器根本没复位。

注意:SPI 触摸屏的驱动里,一定要检查设备树中 spi-max-frequency 的设置。有些廉价屏对时钟频率很敏感,超过 1MHz 就可能丢数据。我建议先从 500kHz 开始试,稳定后再逐步提高。

1.2.3 USB 接口

USB 触摸屏多见于大尺寸交互平板或一体机。它们本质上是一个 HID 设备,内核的 usbhid 驱动可以直接处理。但问题在于——很多 USB 触摸屏厂商不按 HID 规范来,报点格式千奇百怪。

我记得有个项目,客户买了一批 USB 触摸框,插上 Linux 系统后鼠标指针乱跳。后来我抓了 USB 数据包分析,发现厂商把触摸坐标塞进了自定义的 HID 报告描述符里,标准 HID 驱动根本解析不了。最后我只能写了一个内核补丁,重写了报告解析函数。

1.3 触摸屏关键参数解析

驱动移植前,你必须搞清楚几个关键参数。这些参数直接决定了你的驱动怎么写、配置怎么调。

  • 分辨率:触摸屏的物理分辨率,单位是点。比如 1024×768,不是屏幕显示分辨率,而是触摸感应单元的个数。驱动里要把这个值告诉输入子系统。
  • 刷新率:也叫报点率,单位 Hz。普通触摸屏 60Hz 够用,游戏或绘图用的屏可能需要 120Hz 以上。刷新率太低会导致触摸卡顿。
  • 多点触摸点数:同时支持几个触摸点。驱动里需要根据这个值分配内存和协议类型(单点用 EV_KEY,多点用 MT 协议)。
  • 坐标翻转与交换:触摸屏的 X/Y 轴可能和屏幕显示方向不一致。驱动里要做坐标映射,否则点左上角,光标跑到右下角。
参数 说明 驱动中的影响
分辨率 触摸感应单元数量 设置 input_absinfo 的 min/max
刷新率 每秒报点次数 决定中断频率和采样间隔
多点触摸点数 同时支持的触摸点数量 选择单点协议或 MT 协议
坐标翻转 X/Y 轴方向 驱动中做 swap/ invert 处理
压力阈值 电阻屏的按下检测门限 滤波和去抖参数设置

避坑指南:我曾经遇到一块电容屏,分辨率标称是 1920×1080,但实际报出来的坐标范围只有 1800×1000。后来查手册才发现,屏的边缘有一圈无效区域。驱动里必须根据实际有效区域设置 min/max,否则边缘触摸会丢失。

1.4 本章知识体系总览

下面这张图把本章的核心知识点串起来了。你可以把它当作一个快速索引,以后调驱动时忘了什么,回来扫一眼就行。

触摸屏基础知识体系 触摸屏基础:知识体系总览 触摸屏 原理分类 接口协议 关键参数 电阻屏 电容屏 I2C SPI USB 分辨率 刷新率 多点触控 驱动移植前必须确认:原理类型 + 接口协议 + 关键参数 → 缺一不可 💡 我的建议:拿到一块新触摸屏,先看原理图确认接口类型 再读数据手册确认参数,最后才写驱动代码

这张图把本章的三个核心模块串在了一起。你从顶层往下看,先确定触摸屏是电阻还是电容,再看它用什么接口和主控通信,最后把分辨率、刷新率这些参数配好。驱动移植的准备工作就完成了大半。