14. Camera Sensor驱动进阶:HDR模式实现(DOL HDR/Staggered HDR)、高帧率模式配置(Slow Motion)、Sensor OTP/EEPROM读取(LSC/AWB校准数据)、PDAF/激光对焦驱动集成、实战:调试IMX586 Sensor的HDR模式

各位同学,欢迎来到第14章。前面我们聊了Sensor的基础驱动和点亮流程,算是把“能跑”这件事搞定了。但做Camera驱动,光让Sensor出图远远不够。真正的挑战,在于那些“高级功能”——HDR、高帧率、对焦、校准数据读取。这些才是决定产品竞争力的关键。

我个人习惯把这一章叫做“驱动深水区”。因为这里面的坑,真的不少。我当年调试IMX586的HDR模式时,就曾被一个时序问题卡了整整三天。嗯,今天我把这些经验掰开揉碎了讲给你听。

14.1 HDR模式:为什么需要它?

先问个问题:为什么手机拍逆光照片,人脸不黑、背景不过曝?答案就是HDR。HDR的全称是High Dynamic Range,高动态范围。说白了,就是让Sensor同时看清暗处和亮处的细节。

Sensor本身是线性响应的。暗的地方信号弱,亮的地方信号饱和。单次曝光只能照顾一头。HDR的思路很简单:拍多张不同曝光的图像,然后合成。但具体怎么拍、怎么合成,就有讲究了。

14.1.1 DOL HDR vs Staggered HDR

目前主流的Sensor HDR方案有两种:DOL HDR和Staggered HDR。我分别说一下。

特性 DOL HDR Staggered HDR
曝光方式 长短帧交替曝光,独立读出 同一帧内不同行采用不同曝光时间
帧率影响 帧率下降(多帧合成) 帧率基本不变(单帧内完成)
运动伪影 容易产生(帧间运动) 较小(行间运动)
实现复杂度 相对简单 需要Sensor内部支持

DOL HDR,全称Digital Overlap HDR。它的做法是:Sensor连续输出两帧或三帧,每帧曝光时间不同。比如长帧曝光30ms,短帧曝光5ms。ISP拿到这两帧后,做像素级融合。

Staggered HDR则不同。它在一帧内,把不同行的曝光时间错开。比如前几行用长曝光,中间几行用中曝光,后面几行用短曝光。这样一帧就包含了不同曝光信息。好处是帧率不降,坏处是Sensor内部需要支持这种“行级曝光控制”。

核心区别:DOL HDR是“帧间合成”,Staggered HDR是“帧内合成”。前者依赖ISP,后者依赖Sensor本身。

14.2 高帧率模式配置:Slow Motion

慢动作视频,说白了就是高帧率拍摄。比如240fps、480fps甚至960fps。帧率高了,播放时放慢,动作就流畅了。

配置高帧率模式,核心是修改Sensor的帧率寄存器。通常Sensor datasheet里会给出不同分辨率下的最大帧率。比如IMX586在1080p下可以跑到240fps,在4K下只能跑60fps。

我建议你关注三个关键参数:

  • VTS(Vertical Timing Signal):垂直消隐区。减小VTS可以提升帧率。
  • HTS(Horizontal Timing Signal):水平消隐区。一般不动,除非你改行宽。
  • PLL配置:像素时钟频率。提高PLL频率也能提升帧率,但要注意功耗和发热。

举个例子,配置IMX586的1080p 240fps模式,我通常会这样写:

// 设置分辨率
reg_write(0x0340, 0x04);  // 输出高度高字节
reg_write(0x0341, 0x38);  // 输出高度低字节 (1080)

// 设置帧率:减小VTS
reg_write(0x0342, 0x00);  // VTS高字节
reg_write(0x0343, 0x64);  // VTS低字节 (100行消隐)

// 设置PLL
reg_write(0x0301, 0x05);  // PLL倍频
reg_write(0x0305, 0x02);  // PLL分频

注意:高帧率模式下,Sensor的模拟增益和数字增益需要重新校准。我曾经遇到过240fps下画面偏暗的问题,后来发现是增益寄存器没同步更新。嗯,这个坑我踩过。

14.3 Sensor OTP/EEPROM读取:LSC与AWB校准数据

每个Sensor出厂时,都会有一些“个性”。比如镜头边缘亮度不均匀(Lens Shading Correction,LSC),或者白平衡偏差(Auto White Balance,AWB)。这些校准数据就存在Sensor的OTP(One-Time Programmable)或EEPROM里。

读取OTP/EEPROM,通常通过I2C或SPI接口。数据格式各家不同。Sony的Sensor一般用OTP,三星的Sensor喜欢用EEPROM。我个人的经验是:先读datasheet里的“Memory Map”章节,找到校准数据的起始地址和长度。

举个例子,读取IMX586的AWB校准数据:

// 读取OTP数据
uint8_t otp_data[64];
for (int i = 0; i < 64; i++) {
    otp_data[i] = i2c_read(0x0A00 + i);  // OTP起始地址0x0A00
}

// 解析AWB增益
float r_gain = (otp_data[0] << 8 | otp_data[1]) / 256.0f;
float b_gain = (otp_data[2] << 8 | otp_data[3]) / 256.0f;
float gr_gain = (otp_data[4] << 8 | otp_data[5]) / 256.0f;
float gb_gain = (otp_data[6] << 8 | otp_data[7]) / 256.0f;

小技巧:OTP数据通常有校验和(Checksum)。读取后先校验,再使用。我见过不少因为OTP数据损坏导致画面偏色的case。校验不过,就用默认值。

14.4 PDAF/激光对焦驱动集成

对焦是Camera的核心体验之一。PDAF(Phase Detection Auto Focus)和激光对焦是两种主流方案。

PDAF的原理:Sensor上有一些特殊的像素,它们可以检测相位差。驱动根据相位差计算出镜头应该移动的方向和距离。激光对焦则通过发射激光并测量反射时间来计算距离。

集成PDAF驱动,你需要做两件事:

  1. 初始化PDAF模块:配置Sensor内部的PDAF寄存器,使能相位检测功能。
  2. 读取PDAF数据:通过I2C读取相位差数据,然后传给AF算法。

激光对焦驱动相对简单。一般是一个独立的激光传感器(比如VL53L0X),通过I2C或GPIO与主控通信。驱动只需要读取距离值,然后传给AF算法。

我建议你把PDAF和激光对焦的数据融合起来用。PDAF在光线充足时很准,激光对焦在暗光下表现更好。两者互补。

14.5 实战:调试IMX586 Sensor的HDR模式

好了,理论讲完了。我们来点实际的。调试IMX586的HDR模式,我把它分成三步:

14.5.1 第一步:确认Sensor支持哪种HDR

IMX586支持Staggered HDR。具体来说,它内部有一个“多曝光行控制”模块。你需要配置寄存器0x0100(模式选择)和0x0101(帧格式)。

// 使能Staggered HDR模式
reg_write(0x0100, 0x01);  // 进入设置模式
reg_write(0x0101, 0x03);  // 选择Staggered HDR
reg_write(0x0100, 0x00);  // 退出设置模式

14.5.2 第二步:配置长短曝光时间

Staggered HDR需要配置不同行的曝光时间。IMX586提供了两组曝光寄存器:一组用于长曝光行,一组用于短曝光行。

// 配置长曝光时间(30ms)
reg_write(0x0202, 0x0B);  // 长曝光高字节
reg_write(0x0203, 0xB8);  // 长曝光低字节 (3000行)

// 配置短曝光时间(5ms)
reg_write(0x0222, 0x01);  // 短曝光高字节
reg_write(0x0223, 0xF4);  // 短曝光低字节 (500行)

14.5.3 第三步:验证输出

配置完成后,抓一帧raw图。用工具(比如RAW Viewer)查看像素值分布。正常情况下,长曝光行应该偏亮,短曝光行偏暗。如果所有行亮度一致,说明HDR没生效。

避坑指南:我曾经在调试时发现HDR模式下的图像有横条纹。后来排查发现,是VTS设置不对,导致长短曝光行的读出时序冲突。解决办法是:确保VTS大于长曝光时间+短曝光时间+消隐时间。

14.6 本章知识体系

为了让你更直观地理解本章内容,我画了一张流程图。它展示了HDR、高帧率、OTP读取、PDAF/激光对焦之间的关系。

Camera Sensor驱动进阶 HDR模式实现 高帧率模式配置 OTP/EEPROM读取 PDAF/激光对焦 DOL HDR Staggered HDR VTS配置 PLL配置 LSC数据 AWB数据 PDAF 激光对焦 实战:IMX586 HDR模式调试

这张图把本章的知识点串起来了。你看,HDR、高帧率、OTP、对焦,它们不是孤立的。调试HDR时,你可能需要同时调整帧率;读取OTP时,你可能会用到对焦数据。嗯,这就是驱动开发的现实——所有东西都连在一起。

好了,这一章的内容就到这里。记住,调试高级功能时,别急着改代码。先读datasheet,再画时序图,最后动手。我当年要是早点明白这个道理,能少熬好几个通宵。


公众号:蓝海资料掘金营,微信deep3321