2. Sensor选型与驱动适配
Sensor选型,说白了就是给整个摄像头系统挑“眼睛”。眼睛好不好,直接决定了后面ISP、算法、结构设计能不能玩得转。我这些年经手过不下三十款Sensor,从手机模组到车载环视,踩过的坑能写满一本笔记本。今天咱们就聊聊选型时那些绕不开的门道。
2.1 主流Sensor厂商参数对比
目前市面上能打的Sensor厂商,基本就是Sony、OV(OmniVision)和Samsung这三家。每家都有自己的脾气和绝活。
| 对比维度 | Sony | OmniVision | Samsung |
|---|---|---|---|
| 像素工艺 | Exmor RS(堆叠式) | PureCel Plus(背照+堆叠) | ISOCELL(像素隔离) |
| 典型分辨率 | 12MP ~ 48MP | 2MP ~ 64MP | 12MP ~ 108MP |
| 动态范围 | 高(典型72dB+) | 中(典型66dB+) | 中高(典型70dB+) |
| 低光性能 | 优秀(DOL HDR) | 良好(LFM支持) | 良好(Smart-ISO) |
| 驱动生态 | 成熟,文档规范 | 寄存器手册较杂 | 三星平台集成度高 |
| 价格区间 | 偏高 | 中等 | 中等偏低 |
| 典型应用 | 旗舰手机、安防 | 车载、IoT、中低端手机 | 三星手机、安防 |
我个人习惯,做项目选型时先看三个硬指标:帧率、功耗、接口兼容性。举个例子,车载环视项目要求60fps输出,Sony的IMX390系列确实稳,但OV的OV2311在LED闪烁抑制(LFM)上反而更胜一筹。选谁?得看你的场景优先级。
2.2 MIPI CSI-2接口协议详解
Sensor和SoC之间怎么传数据?靠的就是MIPI CSI-2。这个接口协议,说白了就是一套“谁在什么时候说什么话”的规矩。
2.2.1 物理层:D-PHY vs C-PHY
目前主流还是D-PHY,C-PHY在高端平台开始普及。我简单对比一下:
- D-PHY: 差分信号,一对线传一个bit。1 Lane最高2.5Gbps(D-PHY v1.2),4 Lane就是10Gbps。布线要求严格,等长、阻抗控制不能马虎。
- C-PHY: 三线差分,一对线传2.28bit。同样3根线,C-PHY带宽比D-PHY高约30%。但协议复杂,调试工具少。
嗯,这里要注意:不是Lane越多越好。Lane多了,PCB走线难度翻倍,功耗也上去了。我做过一个项目,为了省事选了8 Lane的Sensor,结果板子画了四版才把等长调好。后来学乖了,能用4 Lane绝不用8 Lane。
2.2.2 协议层:帧结构
CSI-2的帧结构,其实就三部分:
- 帧起始包(FS): 告诉接收端“我要开始传一帧了”。
- 行数据包: 每行图像数据,包含行起始、像素数据、行结束。
- 帧结束包(FE): 告诉接收端“这一帧传完了”。
你想想看,如果FS丢了或者FE丢了,SoC就会一直等数据,最后超时报错。我在调试OV的一款Sensor时,就遇到过帧结束包偶尔丢失的问题,查了三天,最后发现是Sensor的VSYNC信号抖动太大,导致SoC误判了帧边界。
2.2.3 数据格式
CSI-2支持多种RAW格式,常见的有:
- RAW8: 每个像素8bit,适合低端Sensor。
- RAW10: 每个像素10bit,主流选择,带宽和画质平衡。
- RAW12: 每个像素12bit,高动态场景用得多。
- RAW14/16: 专业相机或工业场景,带宽压力大。
我建议,移动端项目优先选RAW10。为什么?因为RAW12虽然画质好一点,但带宽增加20%,功耗和发热可能hold不住。车载项目可以上RAW12,毕竟对动态范围要求高。
2.3 驱动移植与初始化时序调试
驱动移植,说白了就是让SoC能“听懂”Sensor说的话。这个过程,我把它拆成三步:
2.3.1 驱动框架适配
Linux内核下,Sensor驱动通常走V4L2框架。你需要实现的核心回调函数包括:
s_power:控制Sensor上电/下电。s_fmt:设置输出格式(分辨率、帧率、数据格式)。g_fmt:获取当前格式。enum_fmt:枚举支持的格式。s_stream:启动/停止数据流。
我记得第一次移植Sony IMX335时,照着参考代码抄了一遍,结果s_stream死活不生效。后来发现是I2C地址写错了——Sony的Sensor默认地址是0x1A,但有些模组厂会改成0x20。嗯,这种低级错误,犯过一次就记住了。
2.3.2 初始化序列配置
Sensor上电后,需要写一串寄存器才能正常工作。这个序列通常包括:
- 软件复位: 让Sensor回到已知状态。
- PLL配置: 设置主时钟、帧率、像素时钟。
- 模拟电路配置: 增益、偏置、ADC参考电压。
- 数字电路配置: 数据格式、输出接口、测试模式。
- 输出使能: 开启MIPI输出。
下面是一个典型的初始化序列示例(伪代码):
// 1. 软件复位
sensor_write(0x0103, 0x01); // 软件复位寄存器
mdelay(10); // 等待复位完成
// 2. 配置PLL
sensor_write(0x0301, 0x05); // PLL倍频系数
sensor_write(0x0303, 0x01); // PLL分频系数
sensor_write(0x0305, 0x02); // 像素时钟分频
// 3. 配置输出格式
sensor_write(0x0112, 0x0A); // 输出RAW10
sensor_write(0x0340, 0x04); // 帧高(高字节)
sensor_write(0x0341, 0x38); // 帧高(低字节)
// 4. 使能MIPI输出
sensor_write(0x0100, 0x01); // 启动流
2.3.3 时序调试实战
时序调试,是驱动移植中最磨人的环节。我总结了一套“三板斧”:
- 抓MIPI波形: 用示波器看D0P/D0N、CLKP/CLKN。确认时钟频率、摆幅、共模电压是否在规格内。
- 看帧同步信号: 用逻辑分析仪抓VSYNC和HSYNC。确认帧率、行周期、消隐区是否正常。
- 读Sensor状态寄存器: 很多Sensor有“错误状态寄存器”,比如Sony的0x0105(错误状态1)、0x0106(错误状态2)。读一下,能快速定位问题。
举个例子,有一次我调试OV的一款Sensor,图像一直有横条纹。用示波器一看,MIPI时钟抖动很大。再查,发现Sensor的MCLK(主时钟)来自SoC的GPIO,那个GPIO的时钟精度只有±5%。换了一个专用的晶振时钟,问题解决。
2.4 Sensor选型与驱动适配知识体系
下面这张图,是我自己总结的Sensor选型与驱动适配的完整知识体系。你可以把它当作一个检查清单,做项目时对着看,不容易漏项。
这张图把Sensor选型、MIPI协议、驱动调试串在了一起。你想想看,做项目时是不是经常在这三个模块之间来回跳?选型没选好,后面协议适配就难受;协议没吃透,驱动调试就抓瞎。所以,我建议你每次做项目前,先把这张图过一遍,心里有个谱。