4. 响应延迟的度量
触摸屏响应这事儿,说白了就是「手指点到屏幕上,系统什么时候能反应过来」。我做了这么多年嵌入式,发现很多产品卡顿、误触、延迟高,根子都出在这四个环节上。今天咱们一个一个拆开聊。
4.1 触摸采样率优化
采样率,就是触摸屏每秒钟报告多少次触摸坐标。单位是 Hz。比如 60Hz 就是每秒 60 次,100Hz 就是每秒 100 次。
采样率越高,延迟越低,但 CPU 负担也越大。 我见过有人把采样率调到 200Hz,结果中断太频繁,系统反而更卡了。嗯,这里要注意平衡。
核心原则:采样率 = 显示刷新率的 1.5~2 倍即可。比如屏幕是 60Hz,采样率 90~120Hz 就够。再高,边际收益递减。
实际项目中,我习惯这样配置:
- 普通场景(菜单、设置页): 60Hz 够用,省电省资源。
- 滑动/翻页场景: 90~120Hz,保证跟手。
- 手写/绘图场景: 150~200Hz,需要精细轨迹。
动态调整采样率是个好办法。我在一个平板项目里做过:检测到手指快速移动时自动升采样率,静止时降下来。效果不错,功耗降了 20%。
4.2 去抖动算法
触摸屏的原始数据,说白了就是一堆「毛刺」。手指按下去,ADC 采样值会上下跳,如果不处理,光标就会乱抖。
去抖动分两种:硬件去抖 和 软件去抖。
4.2.1 硬件去抖
硬件去抖,就是在触摸屏的模拟输出端加 RC 低通滤波器。电容把高频噪声滤掉,电阻限制充放电电流。
我遇到过一个问题:RC 时间常数选大了,触摸响应变慢;选小了,去抖效果差。后来总结出一个经验公式:
τ = R × C ≈ 1 / (2 × π × f_cutoff)
其中 f_cutoff 取触摸信号频率的 3~5 倍。
一般触摸信号频率 ≈ 采样率 / 2,所以:
f_cutoff ≈ (2~3) × 采样率
举个例子:采样率 100Hz,f_cutoff 取 300Hz,τ ≈ 530μs。R 取 10kΩ,C 约 53nF,选 47nF 标准值就行。
小技巧: 硬件去抖只适合滤除高频噪声。对于低频漂移或手指微颤,还得靠软件。
4.2.2 软件去抖
软件去抖,我常用的有三种方法:
| 方法 | 原理 | 适用场景 | 缺点 |
|---|---|---|---|
| 阈值去抖 | 坐标变化超过阈值才更新 | 按键、点击 | 滑动时丢点 |
| 均值滤波 | 取最近 N 个点的平均值 | 滑动、拖拽 | 延迟增加 N/2 个采样周期 |
| 中值滤波 | 取最近 N 个点的中位数 | 有突发噪声的场景 | 计算量大 |
我个人习惯用 加权均值滤波:越新的点权重越大。这样既能去抖,又能保持响应速度。
// 加权均值滤波示例
#define FILTER_TAPS 5
static int weights[FILTER_TAPS] = {1, 2, 3, 4, 5}; // 越新权重越大
static int sum_weights = 15; // 1+2+3+4+5
int filter_touch(int new_x) {
static int buffer[FILTER_TAPS] = {0};
static int index = 0;
int i, filtered = 0;
buffer[index] = new_x;
index = (index + 1) % FILTER_TAPS;
for (i = 0; i < FILTER_TAPS; i++) {
filtered += buffer[(index + i) % FILTER_TAPS] * weights[i];
}
return filtered / sum_weights;
}
避坑指南: 我曾经在一个项目里用了 10 点均值滤波,结果滑动时明显感觉「粘手」。后来改成 5 点加权,延迟从 50ms 降到 20ms,手感好多了。滤波点数不是越多越好。
4.3 触摸预测算法
触摸预测,就是根据历史轨迹,提前算出下一个点的位置。说白了,就是「猜」手指下一步会到哪。
为什么要做预测?因为从触摸采样到屏幕显示,中间有延迟。预测可以补偿这个延迟,让光标更跟手。
我常用的预测算法有两种:
4.3.1 线性预测
假设手指匀速运动。用最近两个点的差,外推下一个点。
// 线性预测
int predict_linear(int x1, int x0) {
return x1 + (x1 - x0); // 速度 = x1 - x0
}
简单,但手指加速或减速时误差大。
4.3.2 二阶预测
考虑加速度。用最近三个点,拟合二次曲线。
// 二阶预测
int predict_quadratic(int x2, int x1, int x0) {
int v = x1 - x0; // 速度
int a = (x2 - x1) - v; // 加速度
return x2 + v + a; // 预测下一个点
}
精度更高,但计算量也大。我一般在手写场景用二阶,普通滑动用线性就够了。
注意: 预测不能太激进。我见过有人预测步长设得太大,结果手指停下时光标还在往前冲,出现「过冲」现象。建议预测步长不超过 2 个采样周期。
4.4 触摸延迟分析
触摸延迟,就是从手指触摸到屏幕显示反馈的总时间。我习惯把它拆成三段:
- 触摸采样延迟: 从触摸发生到 ADC 采样完成。取决于采样率和硬件响应时间。
- 数据处理延迟: 去抖、预测、坐标转换等算法耗时。
- 显示刷新延迟: 从 CPU 送出坐标到屏幕实际显示。取决于显示刷新率和渲染管线。
我画了一张图,帮你理清整个流程:
从图上能看出来,显示刷新延迟往往是最大的瓶颈。60Hz 屏幕,一帧就是 16.7ms。你算法优化得再好,也补不了这个坑。
我有个实际案例:一个 60Hz 屏幕的项目,触摸延迟从 45ms 优化到 28ms。怎么做的?
- 采样率从 60Hz 提到 120Hz(延迟降 8ms)
- 去抖从 8 点均值改成 4 点加权(延迟降 4ms)
- 显示用双缓冲 + 直接刷新(延迟降 5ms)
你看,每个环节抠一点,加起来效果就很明显。
经验之谈: 优化触摸延迟,先测出瓶颈在哪。用 GPIO 打点 + 示波器,能精确测出每段延迟。别凭感觉优化,数据说话。
最后说一句:触摸响应优化没有银弹。采样率、去抖、预测、延迟,四个环节互相牵制。你调高采样率,去抖就得跟上;你加预测,就得防过冲。我习惯的做法是:先定目标延迟(比如 30ms 以内),然后逐段分配预算,再逐个优化。这样心里有数,不会跑偏。