3、调试工具链搭建:IMX335/OV5640传感器驱动配置、MIPI接口调试、I2C读写验证

调试工具链,说白了就是你的「眼睛」和「手」。传感器不上电、MIPI 没波形、I2C 不通,后面 ISP 调得再好也是白搭。这一章我们就把这三件事彻底搞定。

本章核心目标:让 IMX335 和 OV5640 都能正常输出 RAW 数据,MIPI 通道锁定,I2C 读写零误差。

3.1 传感器驱动配置——IMX335 vs OV5640

这两颗 sensor 我都很熟。IMX335 是索尼的 5MP 星光级,动态范围好,适合安防和车载。OV5640 是豪威的 5MP 通用型,便宜、生态好,适合消费类产品。驱动配置上,思路一样,寄存器地址不同。

参数 IMX335 OV5640
分辨率 2592×1944 2592×1944
像素大小 2.0μm 1.4μm
输出接口 MIPI 4-lane / LVDS MIPI 2-lane / 4-lane
I2C 地址 0x1A (7-bit) 0x3C (7-bit)
主时钟 27 MHz / 37.125 MHz 24 MHz
初始化序列长度 ~200 行 ~400 行

我个人习惯把初始化序列写成数组,每行三个值:{reg_addr, reg_val, delay_ms}。这样方便调试时跳过某一步。

// IMX335 初始化片段
static const imx335_reg_t init_seq[] = {
    {0x3000, 0x00, 5},   // 软件复位
    {0x3002, 0x01, 10},  // 等待稳定
    {0x3010, 0x01, 0},   // MIPI 使能
    {0x3011, 0x04, 0},   // 4-lane 模式
    {0x3012, 0x01, 0},   // 时钟配置
    {0x3020, 0x00, 0},   // 帧同步配置
    // ... 省略约 180 行
    {0x3030, 0x10, 100}, // 最后一步:启动输出
};
小技巧:IMX335 的复位后等待时间至少 5ms,OV5640 需要 10ms。我遇到过复位后立刻写寄存器导致 I2C NACK 的情况,加个延时就好了。

3.2 MIPI 接口调试——锁定 D-PHY 信号

MIPI 调试是新手最容易卡住的地方。波形出来了,但 sensor 就是没数据。为什么会这样?多半是时钟 lane 没锁定,或者 data lane 极性反了。

我的调试流程分四步:

  1. 测时钟 lane——用示波器看 HS 模式下是否有 200mV 以上的差分摆幅
  2. 测 data lane 电压——LP 模式 0-1.2V,HS 模式 200mV 差分
  3. 检查极性——DP/DN 是否接反,寄存器里可以翻转
  4. 检查 lane 数匹配——sensor 输出 4-lane,接收端也要配成 4-lane
曾经踩过的坑:有一次 IMX335 死活不出图,示波器看 MIPI 波形完美。折腾了两天,最后发现是 sensor 的 MIPI 驱动电流设成了最低档,信号幅度只有 150mV,接收端锁不住。把寄存器 0x3013 从 0x00 改成 0x03 就好了。

MIPI 调试时,我习惯先配成 2-lane 模式。lane 数越少,信号质量越好,容易先跑通。通了之后再改回 4-lane。

// OV5640 MIPI 配置示例
// 设置 2-lane 模式
i2c_write(0x3C, 0x4800, 0x24);  // MIPI 控制寄存器
// 设置 MIPI 时钟分频
i2c_write(0x3C, 0x4802, 0x01);  // 分频系数
// 使能 MIPI 输出
i2c_write(0x3C, 0x4804, 0x01);  // 输出使能

3.3 I2C 读写验证——从底层保证通信可靠

I2C 是 sensor 调试的命脉。读写不对,后面全是白费。我见过太多人上来就调 ISP,结果发现 sensor ID 都读错了。

验证 I2C 通信,我有一套标准流程:

  • 第一步:读 sensor ID——IMX335 的 ID 寄存器是 0x3000,值应为 0x01;OV5640 的 ID 寄存器是 0x300A,值应为 0x56
  • 第二步:写一个已知寄存器,再读回来——比如写 0x00 到测试寄存器,读回来确认
  • 第三步:连续读写 100 次——看有没有偶发 NACK
  • 第四步:测时序——SCL 频率是否在 100kHz-400kHz 之间
  • // I2C 读写验证函数
    int i2c_verify_sensor(uint8_t slave_addr, uint16_t reg_addr, uint8_t expected_id) {
        uint8_t val = 0;
        int ret;
        
        // 读 sensor ID
        ret = i2c_read_reg(slave_addr, reg_addr, &val);
        if (ret != 0) {
            printf("I2C read failed, addr=0x%02X\n", slave_addr);
            return -1;
        }
        
        if (val != expected_id) {
            printf("Sensor ID mismatch: got 0x%02X, expected 0x%02X\n", val, expected_id);
            return -2;
        }
        
        printf("Sensor ID verified: 0x%02X\n", val);
        return 0;
    }
    避坑指南:IMX335 的 I2C 地址是 7-bit 0x1A,但有些驱动库用 8-bit 地址(0x34)。OV5640 同理,7-bit 0x3C 对应 8-bit 0x78。写代码前先确认你的 I2C 库用哪种格式。

    3.4 整体调试流程——一张图说清楚

    下面这张图是我自己总结的调试流程。每次换 sensor 型号,我都按这个步骤走,基本不会漏东西。

    传感器调试工具链流程图 传感器调试工具链流程图 硬件连接检查 I2C 通信验证 ID 正确? 检查 I2C 时序/上拉 MIPI 时钟调试 MIPI 数据调试 输出 RAW 数据验证 每步通过后打勾,失败则回退到上一步。不要跳步!

    3.5 实战经验——三句话总结

    第一句:I2C 不通,先查上拉电阻和地址格式。我遇到过三次都是因为 7-bit 和 8-bit 地址搞混。

    第二句:MIPI 没数据,先看时钟 lane 的 HS 模式电压。低于 180mV 基本锁不住。

    第三句:初始化序列里,复位后的延时不要省。省了那 5ms,可能多花 5 小时排查。