2、硬件选型与配置:触摸控制器选型、I2C/SPI总线速度配置、中断与轮询模式选择
触摸性能好不好,硬件底子占七成。软件写得再花哨,硬件选错了也白搭。这一章咱们就聊聊触摸控制器的选型、总线怎么配、中断和轮询怎么选。都是实战里踩过的坑,我尽量说得实在点。
2.1 触摸控制器选型:别只看价格
市面上常见的触摸控制器就那么几家:Cypress(现属Infineon)、FocalTech、Goodix、Himax、Synaptics。选型时我习惯先看三个硬指标:
- 报点率(Report Rate):低于80Hz的别考虑,拖拽时明显卡顿
- 多点触控支持:至少5点,最好10点
- 噪声抑制能力:特别是LCD刷新干扰,这个容易被忽略
我个人经验是,FocalTech FT5x06系列在性价比上很能打,I2C接口,报点率能到100Hz,驱动也成熟。如果项目预算充足,Goodix GT911系列在抗干扰和手势识别上更胜一筹。Cypress的TMA系列适合工业场景,但价格偏高。
2.2 I2C vs SPI:总线速度怎么配
触摸控制器和MCU之间通信,主流就两种:I2C和SPI。选哪个?说白了看你的数据量和实时性要求。
| 参数 | I2C | SPI |
|---|---|---|
| 引脚数 | 2(SDA+SCL) | 4(MOSI+MISO+SCLK+CS) |
| 典型速度 | 100kHz~400kHz(标准/快速) | 1MHz~10MHz |
| 单次传输数据量 | 小(通常<64字节) | 大(可连续传输) |
| 多设备支持 | 天然支持(地址寻址) | 需额外CS引脚 |
| 触摸场景推荐 | 低报点率(<80Hz) | 高报点率(>100Hz) |
我建议:如果MCU引脚紧张,选I2C,但速度必须配到400kHz以上。我见过有人用100kHz跑FT5x06,报点率只有30Hz,触摸跟PPT似的。如果引脚够用,SPI是更稳妥的选择,速度配到2MHz以上,报点率轻松上120Hz。
2.3 中断 vs 轮询:选错模式,CPU白忙一半
触摸数据怎么拿?两种方式:中断(Interrupt)和轮询(Polling)。选哪个?我直接给结论:能用中断就别用轮询。
为什么?你想想看,轮询模式下,MCU每隔几毫秒就得去问触摸控制器"有数据吗?",大部分时候答案是"没有"。白白浪费CPU周期。中断模式是触摸控制器主动通知MCU"有数据了,快来拿",CPU该干嘛干嘛,效率高得多。
但中断模式也有坑:
- 中断抖动:触摸控制器在噪声环境下可能频繁触发中断,导致CPU被中断淹没
- 中断优先级:如果触摸中断优先级设得太低,可能被其他中断打断,导致数据丢失
- 中断服务函数要短:ISR里只做数据读取和标志位设置,别做处理
轮询模式什么时候用?我遇到过两种情况:
- MCU没有多余的外部中断引脚了
- 触摸控制器本身不支持中断输出(一些低端芯片确实没有)
如果必须用轮询,我建议轮询间隔不要超过5ms,否则触摸响应会明显滞后。同时配合DMA读取,减少CPU占用。
2.4 实战配置示例:FT5x06 + STM32
拿最常见的FT5x06举例,我一般这么配:
// I2C配置(使用STM32 HAL库)
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 400000; // 400kHz快速模式
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
// 中断配置(下降沿触发)
HAL_GPIO_WritePin(FT5x06_RST_GPIO_Port, FT5x06_RST_Pin, GPIO_PIN_SET);
HAL_Delay(10);
HAL_GPIO_WritePin(FT5x06_RST_GPIO_Port, FT5x06_RST_Pin, GPIO_PIN_RESET);
HAL_Delay(5);
HAL_GPIO_WritePin(FT5x06_RST_GPIO_Port, FT5x06_RST_Pin, GPIO_PIN_SET);
HAL_Delay(50);
// 中断引脚配置(PA0,下降沿触发)
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 中断服务函数(只做标志位设置)
void EXTI0_IRQHandler(void)
{
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET)
{
touch_irq_flag = 1; // 设置标志位,主循环处理
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);
}
}
这个配置跑下来,报点率稳定在100Hz以上,CPU占用不到5%。
2.5 知识体系图:硬件选型与配置决策流程
下面这张图总结了整个决策过程,从选型到配置,一步都不能省。
这张图把整个决策流程串起来了。从选型开始,到总线选择,再到数据获取模式,每一步都有明确的判断依据。我建议你把这个流程贴在工位上,选型时对着走一遍,基本不会漏。
2.6 避坑指南:我踩过的三个坑
做嵌入式这么多年,触摸硬件这块我栽过不少跟头。挑三个典型的说说:
- 坑一:I2C上拉电阻没配好。有一次板子回来,触摸时好时坏,查了两天才发现I2C上拉电阻用了10kΩ,总线上升沿太慢,400kHz跑不稳。换成4.7kΩ就好了。
- 坑二:中断引脚没做滤波。触摸控制器在LCD刷新时会产生毛刺,中断引脚没加RC滤波,导致频繁误触发。后来在中断引脚对地加了个100pF电容,问题解决。
- 坑三:轮询间隔设得太长。有个项目引脚不够只能用轮询,我把间隔设成了10ms,结果触摸拖拽时明显跳点。改成3ms后流畅多了,但CPU占用从8%涨到22%。这就是代价。
好了,这一章就聊到这儿。硬件底子打好了,后面咱们再聊软件层面的优化,比如LVGL的触摸驱动怎么写、数据怎么滤波、手势怎么识别。那些都是锦上添花,但前提是——你的硬件得先跑起来。