4、摄像头硬件接口基础:MIPI CSI-2协议概述、D-PHY物理层、摄像头模组(OV5640/IMX219)数据手册解读
好,咱们进入摄像头驱动开发的第一道门槛——硬件接口。说实话,很多做驱动的兄弟一上来就撸代码,结果板子调不通,最后发现是MIPI的时序配错了,或者干脆物理层就没起来。这活儿我干过,挺折腾的。
这一章,咱们把MIPI CSI-2、D-PHY物理层,还有两个常用模组OV5640和IMX219的数据手册,掰开揉碎了讲清楚。你想想看,搞懂这些,后面写驱动心里才有底。
4.1 MIPI CSI-2协议概述
MIPI CSI-2,全称是Camera Serial Interface 2。说白了,就是摄像头和处理器之间传图像数据的标准协议。为什么要有它?因为传统的并口摄像头(比如DVP)线太多,高分辨率下干扰大,传不远。CSI-2用差分串行传输,线少、抗干扰、速率高。
我个人习惯把CSI-2协议分成三层来看:
- 应用层:定义图像格式,比如RAW8、RAW10、YUV422、JPEG。你从摄像头拿到的数据长什么样,这层说了算。
- 协议层:定义数据怎么打包、怎么分包。比如一帧图像怎么拆成多个包,每个包带什么头。
- 物理层:就是D-PHY,负责把0和1变成差分信号在线上跑。咱们下一节细说。
CSI-2的数据传输,核心是数据包。每个包分两种:
- 长包:传图像数据。结构是:包头(32位,含数据类型、虚拟通道、字计数)+ 数据负载 + 包尾(16位CRC校验)。
- 短包:传控制信息,比如帧同步、行同步。只有32位包头,没有数据负载。
重点:数据类型(Data Type, DT)字段决定了这包数据是RAW10还是YUV422。比如DT=0x2B表示RAW10,DT=0x1E表示YUV422 8位。驱动里解析这个字段,才能正确处理数据。
我在项目中遇到过一个问题:摄像头输出的是RAW10,但驱动按RAW8去解析,结果图像全是条纹。查了半天,才发现是数据类型配错了。嗯,这种坑踩一次就记住了。
4.2 D-PHY物理层
D-PHY是MIPI联盟定义的物理层标准。它用差分信号传输,一对线叫一个Lane。CSI-2最少需要1个Clock Lane(时钟通道)和1个Data Lane(数据通道),最多可以到4个Data Lane。
D-PHY有两种工作模式:
- 高速模式(HS):差分信号,电压摆幅约200mV,速率从80 Mbps到2.5 Gbps per Lane。传图像数据时用这个模式。
- 低功耗模式(LP):单端信号,电压摆幅1.2V,速率只有10 Mbps左右。用于控制信号,比如进入省电状态。
这里有个关键点:D-PHY的时序。从LP模式切换到HS模式,需要经过一个叫"Escape Mode"的序列。具体来说:
LP->HS切换序列:
1. LP-11 (空闲状态)
2. LP-01 (准备)
3. LP-00 (桥接)
4. HS-0 (高速模式开始)
这个序列如果时序不对,物理层就起不来。我曾经在QNX上调试一个IMX219模组,发现D-PHY一直报错,用示波器一抓,发现LP-00的保持时间不够。调整了SoC的D-PHY配置寄存器,问题解决。
注意:D-PHY的时钟通道必须一直运行,数据通道可以按需开关。驱动里要确保时钟通道的PLL锁定后,再使能数据通道。否则数据会丢包。
4.3 摄像头模组数据手册解读
拿到一个摄像头模组,第一件事不是上电,而是读数据手册。我见过有人不看手册直接抄代码,结果摄像头死活不出图。咱们以OV5640和IMX219为例,讲讲怎么看手册。
4.3.1 OV5640数据手册要点
OV5640是OmniVision的500万像素传感器,支持RAW10和JPEG输出。手册里我最关注这几个部分:
- 寄存器映射:OV5640的寄存器地址是16位,数据是8位。比如寄存器0x3008是系统控制,写0x80可以软复位。
- PLL配置:手册里有个PLL计算表,输入主时钟(XVCLK)和输出像素时钟的关系。公式是:
VCO = XVCLK * M / N,然后分频得到像素时钟。 - 输出格式设置:寄存器0x4300控制输出格式。比如设成0x6F表示RAW10,设成0x30表示YUV422。
我的习惯:拿到手册先看"Register Table"章节,找到系统控制、PLL、输出格式这三个关键寄存器组。其他寄存器可以后面再细看。
举个例子,配置OV5640输出640x480 RAW10的步骤:
1. 软复位:写0x80到0x3008,等待10ms
2. 配置PLL:设置0x3034~0x3036,让像素时钟为24MHz
3. 设置分辨率:写0x3808=0x0280 (640),0x3809=0x01E0 (480)
4. 设置输出格式:写0x4300=0x6F (RAW10)
5. 启动输出:写0x3008=0x02
我记得第一次调OV5640时,忘了设置输出格式,默认是YUV422,结果ISP那边一直报格式错误。后来加上格式配置,图像就出来了。
4.3.2 IMX219数据手册要点
IMX219是Sony的800万像素传感器,常用于树莓派Camera v2。它的手册比OV5640更详细,但结构类似。我重点看:
- 模拟增益和数字增益:IMX219的增益控制很精细。模拟增益寄存器0x0157,范围0x00~0xFF,对应1x到16x增益。数字增益寄存器0x0158~0x0159,是12位值。
- 曝光控制:曝光时间由寄存器0x015A~0x015B控制,单位是行时间。比如设成0x03E8(1000行),帧率30fps时,曝光时间约33ms。
- MIPI配置:IMX219支持2-lane MIPI。寄存器0x0112控制lane数,0x0113控制时钟频率。
| 参数 | OV5640 | IMX219 |
|---|---|---|
| 分辨率 | 500万 (2592x1944) | 800万 (3280x2464) |
| 输出格式 | RAW10, JPEG, YUV422 | RAW10, RAW8 |
| MIPI Lane数 | 1~4 Lane | 2 Lane |
| 主时钟 | 6~27 MHz | 6~27 MHz |
| 寄存器地址 | 16位 | 16位 |
IMX219有个坑:它的寄存器写入需要先解锁。寄存器0x0100是模式选择,写0x01进入流模式。但写之前必须确保0x0103=0x01(解锁)。我刚开始没注意,写0x0100没反应,查了半天手册才发现这个解锁步骤。
避坑指南:IMX219的寄存器0x0103是"Register Bank Select",默认是0x00。写0x01才能访问所有寄存器。很多驱动初始化时忘了这步,导致配置无效。
4.4 实战:从数据手册提取关键参数
好了,理论讲完了,咱们来点实际的。假设你要在QNX上驱动一个OV5640模组,你会怎么从手册里提取参数?
我个人习惯按这个顺序来:
- 确定MIPI配置:手册里找"Output Interface"章节,看支持几Lane、最大速率。OV5640支持4 Lane,每Lane最高800 Mbps。
- 计算像素时钟:根据分辨率和帧率,算出需要的像素时钟。比如640x480@30fps,像素时钟约18.4 MHz。
- 配置PLL:根据输入时钟(比如24MHz)和需要的像素时钟,算PLL的M/N分频系数。
- 设置输出格式:找到格式控制寄存器,设成RAW10或YUV422。
- 初始化序列:手册里通常有推荐的初始化序列,直接抄过来用。
举个例子,OV5640的PLL配置计算:
输入时钟:24 MHz
目标像素时钟:24 MHz
PLL配置:
M = 1 (倍频系数)
N = 1 (分频系数)
VCO = 24 * 1 / 1 = 24 MHz
像素时钟 = VCO / 1 = 24 MHz
寄存器设置:
0x3034 = 0x1A (使能PLL)
0x3035 = 0x21 (M=1, N=1)
0x3036 = 0x46 (分频系数)
嗯,这里要注意:不同版本的OV5640,PLL寄存器地址可能不一样。我遇到过手册版本v1.0和v2.0,寄存器0x3035的定义就变了。所以一定要看对应版本的手册。
最后,总结一下这一章的核心:
- CSI-2协议分三层:应用层、协议层、物理层。驱动主要关注协议层的数据包解析。
- D-PHY的LP/HS切换时序很关键,错了物理层起不来。
- 读数据手册时,先找系统控制、PLL、输出格式这三个关键寄存器组。
- IMX219需要先解锁寄存器,OV5640要注意PLL配置的版本差异。
下一章,咱们开始写真正的QNX摄像头驱动。到时候,这些硬件知识都会用上。