4、触摸屏硬件接口:SPI与I2C接口对比、中断引脚配置、复位时序设计

好,咱们进入第四章。这一章聊的是触摸屏的硬件接口,说白了就是芯片之间怎么「说话」的。SPI和I2C这两个接口,做嵌入式的没人不知道。但具体到触摸屏这个场景,选哪个、怎么配、坑在哪,我踩过的坑还真不少。

4.1 SPI vs I2C:接口选型背后的门道

先看一张对比表,这是我做项目时常用的决策依据:

对比项 SPI I2C
引脚数量 4线(CS、SCLK、MOSI、MISO) 2线(SCL、SDA)
通信速率 典型10-50MHz,最高可达100MHz+ 标准100kHz/400kHz,快速1MHz
传输方式 全双工,主从模式 半双工,多主多从
硬件复杂度 简单,无地址仲裁 需要地址匹配和仲裁逻辑
触摸屏适用场景 高刷新率、多点触控、数据量大 低功耗、引脚受限、单点或低速触控

我个人习惯,做工业级POS机时首选SPI。为什么?因为POS机经常要支持多点触控和手势识别,数据量不小。I2C在400kHz下传一次多点坐标数据,延迟明显。你想想看,用户划一下屏幕,等100ms才有反应,这体验能好吗?

但I2C也有它的主场。比如一些低成本的消费级设备,引脚少、走线简单,I2C就够用了。我记得有一次帮客户改方案,他们原来用SPI的触摸屏,但主控芯片的SPI口被占用了,只剩两个I2C引脚。我直接换了颗I2C接口的触控芯片,虽然刷新率从200Hz降到了100Hz,但单点触控完全够用,还省了PCB面积。

我的经验:如果主控芯片的SPI口紧张,可以用GPIO模拟SPI。但注意,模拟SPI的速率受限于GPIO翻转速度,一般只能到几MHz。我曾在STM32F103上模拟过,跑4MHz没问题,再高就丢数据了。

4.2 中断引脚配置:别让CPU空转

触摸屏的中断引脚,是驱动里最容易被忽视的细节。很多人直接配成上升沿触发,结果发现中断频繁触发,CPU负载飙升。

为什么会这样?因为触摸屏在空闲时,中断引脚的电平状态可能不稳定。有些芯片在无触摸时,INT引脚是高阻态,外部需要上拉电阻。如果上拉电阻选得太大,噪声就会耦合进来,产生虚假中断。

我建议的配置方法:

  • 触发方式:优先用下降沿触发。大多数触控芯片在检测到触摸时,INT引脚从高拉低。释放触摸时再拉高。这样每个触摸事件只产生一次中断。
  • 上拉电阻:4.7kΩ到10kΩ之间。我习惯用4.7kΩ,抗噪性好。如果功耗敏感,可以选10kΩ。
  • 去抖处理:中断服务函数里不要直接读坐标。先读状态寄存器确认触摸有效,再读坐标数据。我曾经遇到过中断引脚抖动,连续触发几十次,后来加了5ms的去抖延时才解决。
避坑指南:我曾经在一个项目里,触摸屏的中断引脚和SD卡的CD引脚复用了一个GPIO。结果插拔SD卡时,触摸屏疯狂报中断。排查了两天才发现是引脚冲突。所以,中断引脚一定要独占,别跟其他功能复用。

4.3 复位时序设计:上电顺序决定生死

触摸屏的复位时序,说白了就是芯片上电后,怎么让它进入正常工作状态。很多芯片手册里会写一个时序图,但实际项目中,时序参数往往需要微调。

典型的复位时序包含三个阶段:

  1. 上电稳定期:VDD从0V上升到稳定电压,一般需要1-10ms。这个阶段不要对芯片做任何操作。
  2. 复位脉冲:拉低RST引脚,保持至少1ms(具体看芯片手册)。然后拉高,芯片开始内部初始化。
  3. 初始化等待:拉高RST后,芯片需要一段时间完成内部校准和自检。这个时间从几毫秒到几十毫秒不等。

我常用的复位代码(以SPI接口为例):

// 触摸屏复位函数
void touch_reset(void) {
    // 1. 拉低RST
    HAL_GPIO_WritePin(TOUCH_RST_GPIO_Port, TOUCH_RST_Pin, GPIO_PIN_RESET);
    // 2. 保持低电平10ms(留足余量)
    HAL_Delay(10);
    // 3. 拉高RST
    HAL_GPIO_WritePin(TOUCH_RST_GPIO_Port, TOUCH_RST_Pin, GPIO_PIN_SET);
    // 4. 等待芯片初始化完成(典型值20ms)
    HAL_Delay(20);
    // 5. 发送初始化命令(如设置工作模式、采样率等)
    touch_send_cmd(0x01, 0x00);  // 示例:复位后配置
}
注意:有些触控芯片在复位后,默认是I2C地址0x5A。如果你用的是I2C接口,复位后要重新检测设备地址。我遇到过芯片复位后地址变了,导致通信失败。解决办法是在初始化代码里加一个地址扫描流程。

嗯,这里还要提一个细节:复位时序里的延时,不要用简单的空循环。在RTOS环境下,空循环会阻塞任务调度。我习惯用系统提供的延时函数,比如FreeRTOS的vTaskDelay(),或者HAL库的HAL_Delay()。这样既能保证时序,又不浪费CPU。

最后说一句,触摸屏的硬件接口设计,看似简单,但每个细节都影响最终体验。SPI和I2C选哪个,中断怎么配,复位时序怎么调,这些都是在项目里反复验证过的。你按照这个思路去做,基本不会出大问题。