1. 触摸屏工作原理:电阻屏与电容屏的区别、触摸坐标上报机制、I2C/SPI通信协议基础

做嵌入式驱动这么多年,我调试过最多的外设就是触摸屏。从早期的电阻屏到现在的电容屏,从低速I2C到高速SPI,踩过的坑真不少。这一章我们先打好基础,把触摸屏的工作原理彻底搞清楚。

1.1 电阻屏 vs 电容屏:本质区别在哪?

先说电阻屏。它的结构很简单——两层透明的导电薄膜,中间用微小的绝缘点隔开。你用手指或者任何硬物按下去,两层薄膜就接触了。驱动芯片检测到接触点的电压,就能算出坐标。

我个人习惯把电阻屏叫做「压力感应屏」。因为它必须靠物理形变才能工作。你想想看,戴手套、用笔尖、甚至用信用卡都能操作,这就是它的优势。

电容屏就不一样了。它利用的是人体电场。你的手指靠近屏幕时,会和屏幕表面的电极形成一个耦合电容。芯片检测这个电容变化,就知道你摸在哪了。

核心区别一句话总结:电阻屏靠物理接触,电容屏靠电场感应。电阻屏支持任何物体,电容屏只能识别导体(或者特殊电容笔)。

对比项 电阻屏 电容屏
感应原理 压力导致两层导电膜接触 人体电场改变电极电容
输入方式 手指、笔、任何硬物 手指、电容笔
多点触控 不支持(天生单点) 支持(2~10点)
透光率 较低(约80%) 较高(约90%以上)
耐用性 易磨损,寿命短 表面玻璃,耐磨
成本 低 中高
典型应用 工业控制、POS机 手机、平板、车载

避坑提醒:我曾经在一个工业项目里选了电容屏,结果现场工人戴着手套操作不了,最后被迫换回电阻屏。选型时一定要考虑使用场景,别只看参数。

1.2 触摸坐标上报机制:从物理坐标到应用坐标

触摸屏上报坐标,不是直接把物理位置扔给系统就完事了。中间要经过好几层处理。我画了一张图,帮你理清这个流程。

触摸坐标上报流程 物理触摸 手指/笔接触屏幕 ADC采样 电压/电容值→原始数据 坐标计算 原始值→物理坐标 驱动上报 input子系统 校准/滤波处理 应用层处理 说明: • 电阻屏的ADC采样是X/Y轴分时进行的,先采X再采Y • 电容屏的采样是矩阵扫描,同时检测多个通道的电容变化 • 校准通常在驱动层完成,滤波可以在驱动层或应用层做

这里有个关键点——原始坐标和物理坐标不是一回事。ADC采到的值是一个数字,比如0~4095。这个数字要映射到屏幕的实际像素上。举个例子,如果屏幕分辨率是1024x600,ADC是12位的,那X轴就要把0~4095映射到0~1023。

我的经验:很多新手直接拿ADC值当坐标用,结果触摸位置完全对不上。记住,驱动里一定要做线性映射。公式很简单:screen_x = (adc_x * screen_width) / adc_max。

1.3 I2C/SPI通信协议基础:驱动工程师的必修课

触摸芯片和主控之间怎么通信?目前主流就两种:I2C和SPI。我分别说一下。

1.3.1 I2C协议

I2C只有两根线:SCL(时钟)和SDA(数据)。它是半双工的,靠地址寻址。触摸芯片通常作为从设备,主控通过7位或10位地址访问它。

我调试过一款GT911电容屏,它的I2C地址是0x5D或0x14,取决于复位时的电平。嗯,这里要注意——很多芯片的地址是可以配置的,一定要看数据手册确认。

// I2C读取触摸数据的典型流程
// 以GT911为例
uint8_t gt911_read_points(void)
{
    uint8_t buf[8];
    uint8_t addr = 0xBA;  // 写地址(0x5D << 1)
    
    // 1. 先写寄存器地址
    i2c_start();
    i2c_write_byte(addr);      // 发送设备地址+写
    i2c_write_byte(0x41);      // 状态寄存器地址
    i2c_stop();
    
    // 2. 再读数据
    i2c_start();
    i2c_write_byte(addr | 1);  // 发送设备地址+读
    i2c_read_bytes(buf, 8);    // 连续读取8字节
    i2c_stop();
    
    // 3. 解析坐标
    point.x = (buf[1] << 8) | buf[0];
    point.y = (buf[3] << 8) | buf[2];
    
    return buf[0];  // 返回触摸点数
}

我曾经踩过的坑:I2C通信时,从设备可能因为内部处理没完成而拉低时钟(时钟拉伸)。如果主控不支持时钟拉伸,通信就会卡死。选型时一定要确认主控的I2C控制器是否支持这个特性。

1.3.2 SPI协议

SPI比I2C快得多,全双工,四根线:SCLK、MOSI、MISO、CS。触摸芯片用SPI时,通常CS拉低表示开始通信,SCLK的每个上升沿或下降沿传输一位数据。

我个人更喜欢用SPI调试触摸屏,尤其是那些需要高刷新率的应用,比如游戏手柄或者绘图板。SPI的速率可以跑到几十MHz,而I2C通常只有400kHz或1MHz。

对比项 I2C SPI
线数 2根(SCL, SDA) 4根(SCLK, MOSI, MISO, CS)
通信方式 半双工 全双工
速率 标准100kHz/400kHz,高速3.4MHz 通常10~50MHz
寻址方式 设备地址(7位或10位) 片选信号(CS)
多设备支持 总线挂载多个设备 每个设备独立CS
典型触摸芯片 GT911, FT5x06, TSC2007 ADS7846, TSC2046, XPT2046
// SPI读取触摸数据的典型流程
// 以ADS7846为例
uint16_t ads7846_read_x(void)
{
    uint16_t value;
    
    // 1. 拉低片选
    CS_LOW();
    
    // 2. 发送控制字节:开始位+通道选择+模式
    spi_write_byte(0xD0);  // 0xD0: 开始位1, 通道X+, 12位模式
    
    // 3. 读取2字节数据(实际只有12位有效)
    value = spi_read_byte() << 8;
    value |= spi_read_byte();
    
    // 4. 拉高片选
    CS_HIGH();
    
    // 5. 右移3位得到12位有效值
    return value >> 3;
}

调试技巧:SPI通信时,逻辑分析仪是你的好朋友。我曾经花了一整天找bug,最后发现是SPI的极性(CPOL)和相位(CPHA)配置错了。用逻辑分析仪一看,波形对不上,立马就解决了。

1.4 本章小结

这一章我们讲了三个核心知识点:电阻屏和电容屏的工作原理差异、触摸坐标从物理到应用的上报流程、以及I2C和SPI两种通信协议的基础。这些都是后面做触摸偏移校准和驱动调试的基石。

你想想看,如果连触摸芯片怎么和主控通信都不清楚,那后面做校准算法、调滤波参数的时候,出了问题都不知道从哪查起。所以这一章的内容,我建议你多看几遍,尤其是那个坐标上报流程图,把每个环节都吃透。