原始数据采集:ADC采样原理、触摸点原始数据格式、多点触摸协议
好,咱们进入第二章。上一章聊了触摸屏的基本原理,这一章得扎到最底层——数据是怎么来的。
你想想看,手指按在屏幕上,系统怎么知道你在哪儿按的?这中间有个关键环节:模数转换。说白了,物理世界的模拟信号,得变成数字世界的二进制数,CPU才能处理。
ADC采样原理
ADC,全称模数转换器。它的任务很简单:把连续的电压值,转成离散的数字码。
我刚开始做触摸驱动时,总觉得ADC就是个黑盒子,给个电压就出数字。后来调一个电容屏项目,发现采样值老是跳,才逼着自己把原理啃了一遍。
常见的ADC架构有几种:
| 架构类型 | 分辨率 | 采样率 | 典型应用 |
|---|---|---|---|
| 逐次逼近型(SAR) | 8~16位 | 几M~几十M | 触摸屏、传感器 |
| Σ-Δ型 | 16~24位 | 几K~几M | 高精度测量 |
| 流水线型 | 8~16位 | 几十M~几百M | 视频、通信 |
| 闪存型 | 6~8位 | G级 | 高速示波器 |
触摸屏里用得最多的是SAR ADC。为什么?因为它平衡了速度和精度。我见过一个项目,为了省成本用了8位ADC,结果触摸精度惨不忍睹,后来乖乖换回12位。
关键参数:
- 分辨率:决定了你能区分的最小电压变化。12位ADC,参考电压3.3V,最小分辨率就是3.3V / 4096 ≈ 0.8mV。
- 采样率:每秒能采多少次。触摸屏一般需要100~200Hz,但ADC本身要快得多,因为要扫多个通道。
- 参考电压:直接影响测量范围。我踩过坑,参考电压没接好,采样值漂了10%。
采样过程其实就三步:采样→保持→量化。采样开关打开,电容充电;开关断开,保持电压;然后逐位比较,输出数字码。
我的经验:采样时间一定要够。电容没充满就断开,测出来的值偏小。我一般留2~3个RC时间常数,宁可慢一点,不能错。
触摸点原始数据格式
ADC采完,得到的是原始值。但这个值还不能直接用,得先理解它的格式。
以最常见的电阻屏为例:
- X方向:测量分压比,得到0~4095的原始值(12位ADC)
- Y方向:同样方法,得到另一组原始值
- Z方向:通过压力测量,判断是否按下
但电容屏的数据格式就复杂多了。我调过一个互电容方案,每个节点都是一个原始值:
// 原始数据矩阵示例(5x5节点)
uint16_t raw_data[5][5] = {
{1024, 1022, 1018, 1020, 1023},
{1021, 850, 760, 830, 1019}, // 手指在(1,2)附近
{1023, 780, 690, 760, 1021},
{1022, 840, 750, 820, 1020},
{1025, 1023, 1021, 1024, 1022}
};
看到没?没触摸时,基线值在1024左右。手指按下去,电容变化,值就掉下去了。差值越大,说明触摸越强。
注意:原始数据不能直接用。为什么?因为每个通道的基线不一样,温度、湿度都会漂。我见过一个产品,夏天调好的阈值,冬天全废了。所以一定要做基线校准和动态阈值。
原始数据格式通常包含:
- 触摸ID:区分多个手指
- X坐标原始值:ADC转换结果
- Y坐标原始值:同上
- 压力值:可选,有些方案用面积代替
- 触摸状态:按下、抬起、移动
多点触摸协议
单点触摸好办,一个手指一个坐标。但多点触摸就复杂了——你得告诉系统,哪个手指是哪个,别搞混了。
Linux内核里有个标准协议,叫MT协议(Multi-Touch Protocol)。分两种:
| 协议类型 | 特点 | 适用场景 |
|---|---|---|
| Type A | 无跟踪,每次上报所有触点 | 简单设备,不关心手指ID |
| Type B | 有跟踪,带Slot和ID | 复杂设备,需要手势识别 |
Type B用得最多。它的核心思想是Slot——每个手指占一个槽位,系统通过槽位号来跟踪手指。
// Type B协议上报示例
// 手指1按下
ABS_MT_SLOT 0
ABS_MT_TRACKING_ID 45
ABS_MT_POSITION_X 1200
ABS_MT_POSITION_Y 800
SYN_REPORT
// 手指2按下
ABS_MT_SLOT 1
ABS_MT_TRACKING_ID 46
ABS_MT_POSITION_X 1500
ABS_MT_POSITION_Y 900
SYN_REPORT
// 手指1移动
ABS_MT_SLOT 0
ABS_MT_POSITION_X 1210
ABS_MT_POSITION_Y 810
SYN_REPORT
// 手指1抬起
ABS_MT_SLOT 0
ABS_MT_TRACKING_ID -1
SYN_REPORT
看到没?TRACKING_ID是-1表示手指离开,槽位释放。这个机制我当年调了整整两天才搞明白——一开始没释放ID,系统以为手指一直按着,手势识别全乱了。
协议要点:
- 每个
SYN_REPORT之间是一个完整的触点状态快照 - 同一个手指的
TRACKING_ID必须保持不变 - 槽位可以复用,但释放后要等一个周期再分配
- 最大支持触点数量由硬件决定,一般5~10点
我曾经在一个项目里,为了省内存,把槽位数从10减到5。结果用户三指操作就出问题——第四个手指上来,槽位不够,直接丢点。嗯,后来老老实实改回去了。
数据流全景
把上面这些串起来,整个数据流是这样的:
这张图把整个流程串起来了。从手指按下去,到系统收到坐标,中间经过ADC采样、原始数据生成、校准滤波、协议封装,每一步都可能出问题。
我的建议:调试触摸驱动时,先把原始数据打出来看看。我习惯在ADC采样后加个打印,观察基线值和触摸值的变化。如果原始数据就不对,后面再怎么处理都是白搭。
嗯,这一章的内容就到这儿。ADC采样原理、原始数据格式、多点触摸协议,这三块是触摸校准的基础。下一层咱们要聊的,就是怎么把这些原始数据变成精准的坐标——也就是校准算法。不过那是后面的事了,先把今天的内容消化掉。