3. 硬件同步方案:硬件触发线(GPIO/SPI)同步、外部晶振同步、MIPI CSI 同步机制

各位同学,咱们今天聊点硬核的——硬件同步方案。

说实话,软件同步做得再好,终究是“软”的。你想想看,Android 的 HAL 层再怎么优化,终究绕不开系统调度的不确定性。真正要做到微秒级、甚至纳秒级的同步,还得靠硬件。我在做第一代双摄模组的时候,软件方案折腾了两个月,最后还是老老实实拉了根硬件触发线,问题一下子就解决了。

3.1 硬件触发线同步(GPIO/SPI)

这是最经典、也是最直接的同步方式。说白了,就是主控芯片通过一根 GPIO 线,给所有摄像头模组发一个“开始干活”的信号。

核心原理:主控(AP/ISP)通过硬件触发线(TRIGGER)同时向多个摄像头模组发送触发脉冲,所有模组在接收到脉冲的同一时刻开始曝光。

3.1.1 GPIO 触发模式

GPIO 触发,我习惯叫它“硬拉”。主控把某个 GPIO 口配置成输出模式,然后拉高或拉低,所有摄像头模组的中断引脚检测到电平变化,立即启动曝光。

这里有个关键参数——触发延迟。我曾经在项目中踩过一个坑:GPIO 走线长度不一样,导致触发信号到达各个模组的时间差了 200 纳秒。200 纳秒什么概念?对于 30fps 的帧率来说,可能看不出问题。但如果你在做多摄融合,尤其是深度计算,这 200 纳秒的偏差足以让视差图出现明显的条纹。

我的经验:GPIO 触发线一定要等长布线。如果 PCB 空间不允许,至少保证走线长度差不超过 5mm。另外,建议使用推挽输出,不要用开漏,否则上升沿太慢。

3.1.2 SPI 触发模式

GPIO 触发虽然简单,但有个问题——你只能发一个“开始”信号,没法传参数。SPI 触发就不一样了,你可以通过 SPI 总线发送一帧配置数据,比如曝光时间、增益、甚至 ROI 区域。

我参与过一个 5 摄模组的项目,主控通过 SPI 总线同时向 5 个模组写入同步配置。每个模组有自己的片选(CS)线,但共享 SCLK 和 MOSI。写入完成后,再通过一根公共的 TRIGGER 线同时触发曝光。

// SPI 同步配置示例(伪代码)
void multi_cam_spi_sync(void) {
    // 1. 配置所有模组的曝光参数
    for (int i = 0; i < CAM_NUM; i++) {
        spi_cs_low(i);          // 选中第 i 个模组
        spi_write(REG_EXP_TIME, 0x1234);
        spi_write(REG_GAIN, 0x00FF);
        spi_cs_high(i);
    }
    
    // 2. 等待所有模组配置完成(建议加 1ms 延时)
    delay_ms(1);
    
    // 3. 同时触发所有模组
    gpio_set_level(TRIGGER_PIN, 1);
    delay_us(10);
    gpio_set_level(TRIGGER_PIN, 0);
}

注意:SPI 的时钟频率不能太高,否则长距离传输容易受干扰。我一般控制在 10MHz 以内。另外,SPI 的 CS 线切换之间要留足够的间隔时间,至少 100ns,否则模组可能识别不到片选信号。

3.2 外部晶振同步

GPIO 和 SPI 同步解决的是“触发时刻”的问题,但还有一个更底层的问题——时钟同步。每个摄像头模组都有自己的 PLL,如果各个模组的时钟频率有微小偏差,时间长了就会累积出帧偏移。

举个例子:两个模组都跑 30fps,但一个的时钟是 24.000MHz,另一个是 24.001MHz。看起来只差了 0.001MHz,但运行 1 小时后,两个模组的帧起始时间会偏移大约 150 微秒。这在长时间录制场景下是致命的。

解决方案?给所有模组共用一个外部晶振。

外部晶振同步架构:使用一个高精度温补晶振(TCXO),通过时钟缓冲器(Clock Buffer)扇出多路同频同相的时钟信号,分别供给各个摄像头模组。

我个人习惯选用 24MHz 或 27MHz 的 TCXO,频率稳定性在 ±0.5ppm 以内。时钟缓冲器推荐使用 IDT 或 SiLabs 的型号,扇出能力至少 8 路,附加抖动控制在 1ps 以内。

这里有个容易忽略的点——时钟走线。我曾经在一个项目里,时钟信号走了 10cm 的排线,结果因为阻抗不匹配,信号反射严重,模组直接无法锁定 PLL。后来改成差分时钟传输,问题才解决。

避坑指南:时钟走线一定要做 50Ω 阻抗控制。如果距离超过 5cm,建议使用 LVDS 差分时钟。另外,时钟缓冲器的电源要单独滤波,别跟数字电源混在一起。

3.3 MIPI CSI 同步机制

前面两种方案都是“外部同步”,而 MIPI CSI 同步是“协议层同步”。说白了,就是利用 MIPI CSI-2 协议本身提供的同步机制。

3.3.1 帧同步包(Frame Sync Packet)

MIPI CSI-2 协议定义了一种特殊的短包——帧同步包(Frame Sync Packet)。主控可以通过 CSI 接口发送这个包,所有连接到同一 CSI 总线上的模组都会在收到这个包后同步启动帧传输。

我记得第一次看到这个功能时,觉得特别巧妙。它不需要额外的硬件引脚,直接复用现有的 MIPI 数据通道。但实际用起来,我发现有个限制——它要求所有模组必须共享同一条 MIPI 数据总线。对于多路独立的 MIPI 接口,这个方案就不太适用了。

3.3.2 虚拟通道(Virtual Channel)

MIPI CSI-2 支持 4 个虚拟通道(VC0~VC3)。你可以把多个模组的数据通过不同的虚拟通道复用到同一条 MIPI 数据线上。主控在接收端根据 VC ID 区分数据来源。

这样做的好处是,所有模组共享同一个 MIPI 时钟域,天然就是同步的。但代价是带宽受限——4 个 1080p@30fps 的模组,需要大约 4Gbps 的带宽,而一条 MIPI 4-lane 的极限带宽也就 4.5Gbps 左右,基本跑满了。

同步方式 精度 硬件成本 适用场景
GPIO 触发 微秒级 低(1 根线) 双摄、三摄,帧率不高
SPI 触发 微秒级 中(4~6 根线) 需要动态配置参数的多摄
外部晶振 纳秒级 高(晶振+缓冲器) 长时间录制、高精度同步
MIPI CSI 同步 纳秒级 低(复用数据线) 共享 MIPI 总线的多摄

3.4 三种方案的协同使用

在实际项目中,这三种方案往往不是互斥的,而是协同使用的。我做过的一个 4 摄模组项目,就是“外部晶振 + GPIO 触发 + MIPI 虚拟通道”的组合方案。

具体来说:

  • 所有 4 个模组共用一颗 24MHz TCXO,保证时钟同源
  • 主控通过一根 GPIO 触发线同时启动所有模组的曝光
  • 每个模组的数据通过 MIPI 虚拟通道复用到两条 CSI 接口上(VC0+VC1 走 CSI0,VC2+VC3 走 CSI1)

这样做的效果是,帧同步精度可以做到 1 微秒以内,而且长时间运行也不会出现帧偏移。嗯,这个方案后来成了我们团队的标配。

总结一下我的建议:

  • 如果只是做双摄,GPIO 触发就够了,成本最低
  • 如果需要动态调整参数,上 SPI 触发
  • 如果要做长时间录制或高精度融合,外部晶振必须上
  • 如果 MIPI 接口紧张,考虑虚拟通道复用
硬件同步方案架构图 主控(AP/ISP) TCXO 24MHz 时钟缓冲器 CAM 0 CAM 1 CAM 2 CAM 3 MIPI CSI 数据总线(VC0~VC3 复用) ISP 接收端 外部晶振 GPIO 触发 MIPI CSI 数据

好了,硬件同步方案就讲到这里。这三种方案各有优劣,关键是根据你的项目需求来选。我个人建议,如果条件允许,尽量把外部晶振同步和 GPIO 触发结合起来用,效果最稳。