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 极性反了。
我的调试流程分四步:
- 测时钟 lane——用示波器看 HS 模式下是否有 200mV 以上的差分摆幅
- 测 data lane 电压——LP 模式 0-1.2V,HS 模式 200mV 差分
- 检查极性——DP/DN 是否接反,寄存器里可以翻转
- 检查 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 型号,我都按这个步骤走,基本不会漏东西。
3.5 实战经验——三句话总结
第一句:I2C 不通,先查上拉电阻和地址格式。我遇到过三次都是因为 7-bit 和 8-bit 地址搞混。
第二句:MIPI 没数据,先看时钟 lane 的 HS 模式电压。低于 180mV 基本锁不住。
第三句:初始化序列里,复位后的延时不要省。省了那 5ms,可能多花 5 小时排查。