3. 寄存器访问基础
onsemi 图像传感器(如 AR0144、AR0234、AR0821 等)内部有数百到数千个寄存器,用于控制曝光、增益、帧率、输出格式、PLL、测试图形等。主机(SoC/FPGA/MCU)必须通过 I2C 或 SPI 访问这些寄存器。理解协议层、地址映射、读写时序以及页切换机制,是后续所有寄存器调试工作的基础。
一、I2C 与 SPI:两种物理通道的差异
onsemi 传感器通常同时支持 I2C 和 SPI 两种控制接口,二者在电气层和协议层差异明显:
- I2C:两线(SCL/SDA),7 位从机地址(常见 0x30、0x36、0x3C、0x6C 等,取决于具体型号和 SADDR 引脚电平),支持标准 100 kHz、快速 400 kHz、快速+ 1 MHz。总线上可挂多个器件,靠地址区分。每次读写都要经历 START、从机地址+读写位、ACK、寄存器地址、ACK、数据、ACK、STOP。
- SPI:四线(CSN、SCK、SDI、SDO),全双工,速率可达数十 MHz。onsemi 传感器 SPI 通常采用 16 位地址 + 8 位数据的帧格式,读写由最高位(R/W 位)区分。SPI 没有 ACK 机制,靠回读校验确认写入成功。
选择原则:初始化阶段寄存器写入量大、要求快,可用 SPI;运行中少量动态调整(如曝光、增益)用 I2C 更省引脚。若两者同时存在,需注意部分型号同一寄存器在两种接口下地址一致,但字节序或位域定义可能不同,务必以对应数据手册为准。
二、寄存器地址映射:16 位地址空间与页结构
onsemi 传感器的寄存器地址通常是 16 位(0x0000–0xFFFF),但 I2C/SPI 单次传输的地址字段往往只有 8 位或 16 位。为覆盖更大的地址空间,芯片内部把地址空间划分为多个“页(Page)”,每页 256 字节(低 8 位为页内偏移,高 8 位为页号)。访问某个寄存器时,需要先写“页选择寄存器”切换到目标页,再访问页内偏移。
典型映射关系(以某型号为例,具体以数据手册为准):
| 页号 | 地址范围 | 主要内容 |
|---|---|---|
| 0x00 | 0x0000–0x00FF | 核心控制:软复位、PLL、帧率、输出格式 |
| 0x01 | 0x0100–0x01FF | 曝光、增益、黑电平 |
| 0x02 | 0x0200–0x02FF | ROI、镜像、开窗 |
| 0x03 | 0x0300–0x03FF | 测试图形、GPIO、状态 |
注意:页选择寄存器本身通常位于第 0 页的固定偏移(例如 0x30FE 或 0x301A 等),切换页后该寄存器可能不可见,因此切换前要记住当前页,或每次访问都显式重设页号。
三、读写时序:一次完整访问发生了什么
以 I2C 写一个 16 位地址寄存器为例,典型时序如下:
START
从机地址 + W(0) → 传感器 ACK
地址高字节 → 传感器 ACK
地址低字节 → 传感器 ACK
数据字节 → 传感器 ACK
STOP
读操作分两段:先写地址(同上,但不发数据),再发 Repeated START + 从机地址 + R(1),然后读取数据字节,主机发 NACK 后 STOP。SPI 则把地址和数据放在同一帧中,CSN 拉低后连续发送 16 位地址(最高位为 R/W),随后在 SCK 边沿采样数据。
关键时序参数:I2C 的 tSU:DAT、tHD:DAT、tLOW、tHIGH 必须满足手册要求;SPI 的 SCK 极性/相位(CPOL/CPHA)必须与传感器一致,onsemi 通常为 CPOL=0、CPHA=0(模式 0)。若时序不满足,会出现写入无效、回读全 0 或全 FF 的现象。
四、页切换与多字节访问
页切换的本质是“先写页寄存器,再访问目标地址”。多字节访问有两种常见形式:
- 连续地址自增:部分传感器支持地址自动递增,一次传输可连续读写多个相邻寄存器,适合批量初始化。但并非所有型号都支持,需查手册确认。
- 逐寄存器访问:每次单独发地址+数据,最稳妥,兼容性最好,但速度慢。
实际工程中,初始化序列通常写成“页号 + 地址 + 值”的三元组列表,由驱动按顺序执行。若某次写入后回读不一致,优先检查页号是否被意外改变、地址是否越界、以及 I2C 上拉电阻和总线电容是否导致波形畸变。
五、实操示例:一次完整的页切换写入
假设要把 0x0136 寄存器写为 0x5A,使用 I2C 从机地址 0x36(7 位),操作序列如下:
// 1. 切换到第 1 页(页选择寄存器位于第 0 页 0x30FE)
I2C_Write(0x36, 0x30, 0xFE, 0x01);
// 2. 写目标寄存器 0x0136 = 0x5A
I2C_Write(0x36, 0x01, 0x36, 0x5A);
// 3. 回读校验
uint8_t val = I2C_Read(0x36, 0x01, 0x36);
if (val != 0x5A) {
// 检查页号是否仍为 0x01,或重试
}
若使用 SPI,帧格式通常为:CSN 拉低 → 发送 16 位地址(最高位 0 表示写)→ 发送 8 位数据 → CSN 拉高。读操作时最高位为 1,随后在 SCK 下降沿采样 SDO。