2. 嵌入式系统与触摸交互基础

在 Qt 嵌入式触摸交互开发中,界面能否稳定响应,往往不取决于 Qt 控件本身,而取决于底层输入链路是否打通。嵌入式 Linux 把显示抽象为帧缓冲(framebuffer),把按键、触摸、鼠标等统一抽象为输入子系统(input subsystem)。理解这两条主线,才能解释“为什么屏幕有画面但触摸没反应”“为什么坐标总是偏移”“为什么单点正常、多点丢失”等典型问题。

一、嵌入式 Linux 的显示与输入抽象

嵌入式 Linux 通常由 Bootloader、Kernel、Rootfs 和应用程序组成。对 Qt 应用而言,最关心的是内核暴露给用户空间的两类设备节点:显示设备 /dev/fb0 和输入设备 /dev/input/eventX。帧缓冲负责“画到哪里”,输入子系统负责“谁点了哪里”。

帧缓冲是一块连续显存,应用通过 mmap 映射后可直接写入像素。它不关心控件、窗口和图层,只描述分辨率、色深、行跨度(stride)和像素格式。输入子系统则由内核统一管理,事件以 struct input_event 形式上报,包含时间戳、类型、代码和值。触摸屏通常上报 EV_ABS 绝对坐标事件,按键上报 EV_KEY,同步由 EV_SYN 完成。

嵌入式 Linux 触摸交互数据链路 触摸面板 电容/电阻感应 产生模拟信号 触摸控制器 I2C / SPI / USB 中断 + 坐标转换 内核输入子系统 input core / evdev EV_ABS / EV_KEY /dev/input/eventX 用户空间事件流 Qt 读取并分发 GPU / 显示控制器 LCD 时序与图层 输出到面板 帧缓冲 /dev/fb0 mmap 显存映射 RGB565 / ARGB8888 Qt 平台插件 linuxfb / eglfs evdev / libinput Qt 触摸事件 QTouchEvent QMouseEvent 事件驱动 关键参数与节点 显示:/dev/fb0、分辨率、stride、像素格式、双缓冲 输入:/dev/input/eventX、ABS_X/ABS_Y、ABS_MT_SLOT、ABS_MT_POSITION_X/Y、EV_SYN

二、触摸屏工作原理与常见接口

触摸屏由“感应面板 + 控制器”组成。电阻屏通过压力使上下导电层接触,控制器测量电压分压得到 X/Y;电容屏通过检测人体与电极之间的电容变化定位,支持多点触控。控制器完成采样、滤波、坐标计算后,经 I2C、SPI 或 USB 把数据交给主控。主控内核驱动再把它翻译成标准输入事件。

常见接口对比如下:

接口类型 典型速率 引脚/连线 适用场景 注意事项
I2C 100k~400kHz SCL、SDA、INT、RST 中小尺寸电容屏 地址冲突、上拉电阻、中断触发方式
SPI 数 MHz~数十 MHz SCLK、MOSI、MISO、CS、INT 高刷新率触摸控制器 片选、时钟极性、DMA 传输
USB 12Mbps/480Mbps D+、D-、VBUS、GND 外接触摸屏、工控一体机 枚举、HID 多点协议、热插拔
RGB/LVDS 并行 像素时钟 数据线、时钟、DE、HSYNC、VSYNC 显示与触摸一体模组 时序匹配、EMI、走线等长

三、从设备节点到 Qt 事件的完整流程

以电容屏为例,一次点击的完整路径如下:

  1. 手指靠近面板,电容变化被触摸控制器采集。
  2. 控制器通过 I2C 中断通知主控,主控读取坐标数据。
  3. 内核驱动调用 input_report_abs() 上报 ABS_MT_POSITION_X/Y,再调用 input_sync() 结束一帧。
  4. evdev 把事件写入 /dev/input/eventX。
  5. Qt 平台插件读取事件,转换为 QTouchEvent 或 QMouseEvent。
  6. Qt 根据坐标命中控件,触发 pressed、moved、released 信号。

调试时可用以下命令快速确认输入设备是否正常:

# 查看输入设备列表
cat /proc/bus/input/devices

# 实时查看触摸事件
hexdump -C /dev/input/event1

# 使用 evtest 查看事件类型与坐标
evtest /dev/input/event1

# 查看帧缓冲信息
fbset -i
cat /sys/class/graphics/fb0/virtual_size

四、典型场景与排障复盘

场景一:屏幕显示正常,但触摸无响应。先确认 /dev/input/eventX 是否存在,再用 evtest 观察是否有 EV_ABS 事件。若没有事件,问题在硬件连接、驱动或中断;若有事件但 Qt 无反应,检查 Qt 平台插件是否启用 evdev,以及 QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS 是否配置正确。

场景二:触摸坐标偏移或镜像。常见原因是触摸屏与显示屏分辨率不一致、坐标未做仿射变换,或 ABS_X/ABS_Y 的最小最大值与面板不匹配。可通过 evtest 记录实际坐标范围,再在 Qt 或驱动层做线性映射。

场景三:单点正常,多点丢失。需要确认控制器是否支持多点协议,内核是否上报 ABS_MT_SLOT 和 ABS_MT_TRACKING_ID。若只上报单点,Qt 只能得到单点触摸。

常见误区:把触摸问题直接归因于 Qt 控件。实际上,绝大多数“点不动”来自设备节点、权限、驱动上报格式或平台插件配置。建议按“硬件连接 → 内核事件 → 设备节点 → Qt 插件 → 控件响应”的顺序逐层排查,避免在应用层反复修改却忽略底层输入链路。

实践建议:在目标板上固定保留 evtest、hexdump、fbset 等工具;为触摸设备设置稳定的 udev 规则,避免 event 编号变化导致 Qt 找不到设备;对坐标做校准参数持久化,便于不同批次屏幕复用同一套 Qt 程序。