3. Sensor上电时序与初始化:电源管理与时钟树

Sensor 能不能正常工作,第一步就看上电时序。我见过不少项目,代码写得没问题,但 sensor 就是不出图,最后查出来是电源没按规矩来。说白了,sensor 是个精密的模拟器件,供电顺序错了,轻则不出图,重则直接烧掉。

3.1 三路电源的来龙去脉

大部分 CMOS sensor 需要三路独立电源:

电源轨 典型电压 供电对象 电流需求
DVDD 1.2V / 1.8V 数字核心逻辑、ISP 前端 几十 ~ 几百 mA
AVDD 2.8V / 3.3V 模拟像素阵列、ADC 几十 ~ 几百 mA
IOVDD 1.8V / 2.8V I/O 接口、MIPI、I2C 几 ~ 几十 mA

这里有个容易踩的坑:IOVDD 必须和主控端的 MIPI 或 DVP 接口电平匹配。我之前做过一个项目,主控是 1.8V 的 MIPI PHY,结果 sensor 的 IOVDD 用了 2.8V,画面一直有横纹干扰。查了两天才发现是电平不匹配导致的信号反射。

3.2 上电时序:先模拟后数字

业界通用的上电顺序是:

  1. 先上 AVDD —— 模拟域先稳定
  2. 再上 DVDD —— 数字域后启动
  3. 最后上 IOVDD —— 接口最后就绪

为什么是这个顺序?你想想看,模拟像素阵列需要干净的电源环境。如果数字域先上电,数字开关噪声会通过衬底耦合到模拟区,导致暗电流不均匀。我习惯在 AVDD 和 DVDD 之间留至少 1ms 的延迟。

关键指标:大多数 sensor 要求 AVDD 与 DVDD 之间的上升时间差在 0.1ms ~ 10ms 之间。具体数值请以 datasheet 中的 "Power-Up Sequence Timing Diagram" 为准。

3.3 下电时序:反过来

下电顺序和上电正好相反:

  • 先断 IOVDD
  • 再断 DVDD
  • 最后断 AVDD

为什么要这样?因为 IOVDD 先断,可以防止 MIPI 接口在掉电过程中向主控反向灌电流。我遇到过一块板子,下电顺序搞反了,每次关机后 sensor 都会发热,最后发现是 AVDD 通过 ESD 保护二极管倒灌到了 IOVDD 上。

注意:有些 sensor 支持 "Power Down" 模式,此时只需要关掉 AVDD,DVDD 和 IOVDD 保持即可。但一定要确认 datasheet 中是否有这种特殊模式。

3.4 Reset 与 Standby 时序

电源稳定后,接下来就是复位操作。一般有两种复位方式:

  • 硬件复位(Reset Pin):拉低至少 1ms,然后释放
  • 软件复位(Register Reset):通过 I2C/SPI 写寄存器

我个人习惯先用硬件复位,再用软件复位做二次确认。为什么?因为硬件复位能保证所有寄存器回到默认值,包括那些 datasheet 里没写出来的保留位。

Standby 时序相对简单:

  • 进入 Standby:拉高 Standby Pin 或写寄存器
  • 退出 Standby:拉低后等待至少 1ms 再开始配置

经验之谈:我曾经在量产测试中发现,有些 sensor 从 Standby 唤醒后第一帧图像偏暗。后来加了 2ms 的等待时间,问题就解决了。所以别太相信 datasheet 上的最小值,留点余量没坏处。

3.5 PLL 配置与时钟树

时钟是 sensor 的心脏。PLL 配置错了,整个 sensor 的帧率、数据速率都会乱套。

典型的 sensor 时钟树长这样:

Sensor 时钟树结构 外部晶振 (XCLK) PLL 倍频 分频器 像素时钟 (PCLK) MIPI 时钟 内部逻辑时钟 时钟配置要点: • PLL 输出频率 = XCLK × (M / N),其中 M 为倍频系数,N 为分频系数 • 像素时钟 = PLL 输出 / 分频比,决定了行读出速率 • MIPI 时钟 = PLL 输出 / MIPI 分频比,决定了数据传输带宽

3.6 PLL 配置实战

假设我们有一个 sensor,外部晶振是 24MHz,目标帧率是 30fps,分辨率是 1920x1080。怎么配 PLL?

先算像素时钟:

每行像素 = 1920 + H_Blank(假设 280)
每帧行数 = 1080 + V_Blank(假设 45)
总像素 = (1920 + 280) × (1080 + 45) = 2200 × 1125 = 2,475,000
像素时钟 = 总像素 × 帧率 = 2,475,000 × 30 = 74.25 MHz

然后算 PLL 倍频系数:

PLL 输出 = 74.25 MHz
倍频系数 M = 74.25 / 24 = 3.09375
取整:M = 3,N = 1
实际 PLL 输出 = 24 × 3 / 1 = 72 MHz
实际帧率 = 72,000,000 / 2,475,000 ≈ 29.09 fps

嗯,差了将近 1fps。这时候可以调整 H_Blank 或 V_Blank 来微调帧率。我一般会优先调 H_Blank,因为对图像质量影响最小。

核心公式:

帧率 = PLL_Output / (H_Total × V_Total)

MIPI 数据速率 = PCLK × MIPI_Lanes × 2(DDR 模式)

3.7 初始化流程总结

一个完整的 sensor 初始化流程应该是:

  1. 上电:AVDD → DVDD → IOVDD,每步间隔 1ms
  2. 等待电源稳定:至少 5ms
  3. 硬件复位:拉低 Reset Pin 1ms,释放
  4. 等待复位完成:至少 2ms
  5. 配置 PLL:写倍频系数、分频系数
  6. 等待 PLL Lock:轮询状态寄存器或等待 5ms
  7. 配置 sensor 寄存器:曝光、增益、输出格式等
  8. 启动输出:写 Start/Enable 寄存器

血的教训:我曾经跳过第 6 步,以为 PLL 锁得很快。结果 sensor 输出了一堆花屏,查了半天才发现 PLL 还没锁定就开始读数据了。从那以后,我每次都会读 PLL Lock 状态寄存器做确认。