OV7725 内部时钟版本

元器件
传感器
库存 400

介绍

OmniVision OV7725 VGA(640x480) CMOS图像传感器,主打高速和低照度性能,支持60fps@VGA。内部时钟版本集成PLL,仅需单一参考时钟。广泛应用于无人机、机器人视觉、工业检测等需要高速低延迟的场景。

规格参数

参数
像素VGA 30万(640x480)
封装CSP-28
信噪比50dB
供电电压内核1.8V(内部LDO), 模拟3.3V, I/O 1.8V-3.3V
像素尺寸6.0μm x 6.0μm
动态范围72dB
时钟方案内部PLL,参考时钟6-27MHz
最大帧率60fps@VGA(640x480), 120fps@QVGA
特色功能高灵敏度6.0μm大像素、低照度优异(0.5lux)、支持RawRGB/YUV/RGB565
输出接口DVP 8/10位并行
传感器尺寸1/4英寸

代码例程

OV7725 内部时钟版本驱动代码例程.md

# OV7725 内部时钟版本驱动代码例程

## 一、平台说明

- **主控平台**:STM32F407 / OpenMV / ESP32-S3
- **接口类型**:DVP 8位并行
- **SCCB地址**:0x42(7位 0x21)
- **特点**:无页寻址,直接寄存器访问

---

## 二、SCCB 驱动(无页寻址)

```c
#include "stm32f4xx_hal.h"

// OV7725 SCCB 地址
#define OV7725_I2C_ADDR  0x42  // 7位地址0x21左移1位

I2C_HandleTypeDef hi2c1;

void OV7725_I2C_Init(void)
{
    __HAL_RCC_I2C1_CLK_ENABLE();
    hi2c1.Instance = I2C1;
    hi2c1.Init.ClockSpeed = 100000;
    hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
    hi2c1.Init.OwnAddress1 = 0;
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    HAL_I2C_Init(&hi2c1);
}

// OV7725 寄存器写入(8位地址,无需页切换!)
uint8_t OV7725_WriteReg(uint8_t reg, uint8_t data)
{
    uint8_t buf[2];
    buf[0] = reg;
    buf[1] = data;
    return HAL_I2C_Master_Transmit(&hi2c1, OV7725_I2C_ADDR, buf, 2, 100);
}

uint8_t OV7725_ReadReg(uint8_t reg)
{
    uint8_t data = 0;
    HAL_I2C_Master_Transmit(&hi2c1, OV7725_I2C_ADDR, &reg, 1, 100);
    HAL_I2C_Master_Receive(&hi2c1, OV7725_I2C_ADDR | 0x01, &data, 1, 100);
    return data;
}
```

---

## 三、内部PLL时钟配置

```c
// =============================================
// OV7725 内部PLL配置(VGA 60fps)
// XVCLK=24MHz → PCLK=24MHz (VGA 60fps)
// =============================================
void OV7725_ConfigPLL_Internal(void)
{
    printf("配置 OV7725 内部 PLL...\r\n");

    // COM4: PLL控制
    OV7725_WriteReg(0x0D, 0x41);  // COM4: PLL使能

    // 时钟控制
    OV7725_WriteReg(0x11, 0x01);  // CLKRC: 内部PLL使能, 不分频
    // bit[6]: 保留
    // bit[5]: 直接使用PLL输出
    // bit[4:0]: PCLK分频系数

    // PLL配置寄存器
    OV7725_WriteReg(0x2A, 0x00);  // PLL控制1
    OV7725_WriteReg(0x2B, 0x00);  // PLL控制2

    // PCLK分频: PCLK = SCLK / (CLKRC[4:0]+1)
    // 若SCLK=48MHz, CLKRC=1 → PCLK=24MHz
    OV7725_WriteReg(0x11, 0x01);  // PCLK = SCLK/2

    HAL_Delay(5);  // PLL锁定

    printf("OV7725 PLL配置完成: PCLK≈24MHz\r\n");
}
```

---

## 四、VGA 60fps 高速初始化序列

```c
// =============================================
// OV7725 硬件上电
// =============================================
void OV7725_HardwareInit(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_8;   // PWDN
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_0;   // RESET
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);  // PWDN=0
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);  // RESET=0
    HAL_Delay(10);

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);    // PWDN=1
    HAL_Delay(5);  // 内部PLL需锁定

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);    // RESET=1
    HAL_Delay(20);
}

// =============================================
// OV7725 VGA 60fps RGB565 初始化
// =============================================
void OV7725_Init_VGA_60fps(void)
{
    printf("OV7725 VGA 60fps 初始化...\r\n");

    // ---- 软件复位 ----
    OV7725_WriteReg(0x12, 0x80);
    HAL_Delay(100);

    // ---- 输出格式: VGA RGB565 ----
    OV7725_WriteReg(0x12, 0x06);  // COM7: VGA分辨率, RGB格式

    // ---- 时钟配置(内部PLL)----
    OV7725_WriteReg(0x11, 0x01);  // CLKRC: PCLK=SCLK/2
    OV7725_WriteReg(0x0D, 0x41);  // COM4: PLL使能

    // ---- 分辨率窗口: VGA 640x480 ----
    OV7725_WriteReg(0x17, 0x21);  // HSTART
    OV7725_WriteReg(0x18, 0xA1);  // HSTOP
    OV7725_WriteReg(0x19, 0x01);  // VSTART
    OV7725_WriteReg(0x1A, 0xE1);  // VSTOP
    OV7725_WriteReg(0x32, 0x21);  // HREF
    OV7725_WriteReg(0x33, 0xA1);  // HREF
    OV7725_WriteReg(0x03, 0x01);  // VREF
    OV7725_WriteReg(0x04, 0xE1);  // VREF

    // ---- 输出窗口 640x480 ----
    OV7725_WriteReg(0x51, 0x02);  // OUTW高
    OV7725_WriteReg(0x52, 0x80);  // OUTW低 → 640
    OV7725_WriteReg(0x53, 0x01);  // OUTH高
    OV7725_WriteReg(0x54, 0xE0);  // OUTH低 → 480

    // ---- 时序 ----
    OV7725_WriteReg(0x55, 0x00);  // HTS
    OV7725_WriteReg(0x56, 0x00);  // HTS
    OV7725_WriteReg(0x57, 0x00);  // VTS

    // ---- 自动控制 ----
    OV7725_WriteReg(0x13, 0x07);  // COM8: AEC/AGC/AWB使能
    OV7725_WriteReg(0x14, 0x08);  // COM9: 增益上限4x
    OV7725_WriteReg(0x22, 0x00);  // AWB控制
    OV7725_WriteReg(0x24, 0x78);  // AGC/AEC稳定
    OV7725_WriteReg(0x25, 0x68);  // AEC目标
    OV7725_WriteReg(0x26, 0xD0);  // AGC增益上限
    OV7725_WriteReg(0x2C, 0x00);  // 亮度

    // ---- 图像质量 ----
    OV7725_WriteReg(0x41, 0x00);  // 锐度
    OV7725_WriteReg(0x4F, 0x80);  // 矩阵系数
    OV7725_WriteReg(0x50, 0x80);  // 矩阵系数
    OV7725_WriteReg(0x51, 0x00);  // 矩阵系数
    OV7725_WriteReg(0x52, 0x22);  // 矩阵系数
    OV7725_WriteReg(0x53, 0x5E);  // 矩阵系数
    OV7725_WriteReg(0x54, 0x80);  // 矩阵系数

    // ---- 高速优化 ----
    OV7725_WriteReg(0x2D, 0x00);  // 高速模式
    OV7725_WriteReg(0x2E, 0x00);  // 高速模式

    // ---- COM3: 输出使能 ----
    OV7725_WriteReg(0x0C, 0x00);  // COM3: 正常输出

    // ---- 最终启动 ----
    OV7725_WriteReg(0x12, 0x06);  // COM7: 启动输出

    printf("OV7725 VGA 60fps 初始化完成\r\n");
}
```

---

## 五、高速采集示例

```c
#define FRAME_WIDTH   640
#define FRAME_HEIGHT  480
#define FRAME_SIZE    (FRAME_WIDTH * FRAME_HEIGHT * 2)

__attribute__((aligned(4))) uint8_t frame_buffer[FRAME_SIZE];
volatile uint8_t frame_ready = 0;

DCMI_HandleTypeDef hdcmi;
DMA_HandleTypeDef hdma_dcmi;

void DCMI_Init(void)
{
    __HAL_RCC_DCMI_CLK_ENABLE();
    __HAL_RCC_DMA2_CLK_ENABLE();

    hdcmi.Instance = DCMI;
    hdcmi.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE;
    hdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_FALLING;
    hdcmi.Init.VSPolarity = DCMI_VSPOLARITY_LOW;
    hdcmi.Init.HSPolarity = DCMI_HSPOLARITY_LOW;
    hdcmi.Init.CaptureRate = DCMI_CR_ALL_FRAME;
    hdcmi.Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;
    hdcmi.Init.JPEGMode = DCMI_JPEG_DISABLE;
    HAL_DCMI_Init(&hdcmi);

    hdma_dcmi.Instance = DMA2_Stream1;
    hdma_dcmi.Init.Channel = DMA_CHANNEL_1;
    hdma_dcmi.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_dcmi.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_dcmi.Init.MemInc = DMA_MINC_ENABLE;
    hdma_dcmi.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_dcmi.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_dcmi.Init.Mode = DMA_CIRCULAR;  // 高速连续采集
    hdma_dcmi.Init.Priority = DMA_PRIORITY_VERY_HIGH;
    HAL_DMA_Init(&hdma_dcmi);
    __HAL_LINKDMA(&hdcmi, DMA_Handle, hdma_dcmi);
}

void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
{
    frame_ready = 1;
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    UART_Init();

    printf("=== OV7725 内部时钟版本 VGA 60fps ===\r\n");

    OV7725_I2C_Init();
    OV7725_HardwareInit();
    OV7725_ConfigPLL_Internal();
    OV7725_Init_VGA_60fps();

    DCMI_Init();
    HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_CONTINUOUS,
                       (uint32_t)frame_buffer, FRAME_SIZE / 4);

    uint32_t frame_count = 0;
    uint32_t last_tick = HAL_GetTick();

    while (1)
    {
        if (frame_ready)
        {
            frame_ready = 0;
            frame_count++;

            if (HAL_GetTick() - last_tick >= 1000)
            {
                printf("FPS: %lu\r\n", frame_count);
                frame_count = 0;
                last_tick = HAL_GetTick();
            }
        }
    }
}
```

---

## 六、ESP32 平台示例

```c
#include "esp_camera.h"

static camera_config_t camera_config = {
    .pin_pwdn       = 32,
    .pin_reset      = 33,
    .pin_xclk       = 0,         // 24MHz
    .pin_sccb_sda   = 26,
    .pin_sccb_scl   = 27,
    .pin_d7         = 35,
    .pin_d6         = 34,
    .pin_d5         = 39,
    .pin_d4         = 36,
    .pin_d3         = 21,
    .pin_d2         = 19,
    .pin_d1         = 18,
    .pin_d0         = 5,
    .pin_vsync      = 25,
    .pin_href       = 23,
    .pin_pclk       = 22,

    .xclk_freq_hz   = 24000000,
    .ledc_timer     = LEDC_TIMER_0,
    .ledc_channel   = LEDC_CHANNEL_0,

    .pixel_format   = PIXFORMAT_RGB565,
    .frame_size     = FRAMESIZE_VGA,

    .fb_count       = 2,
    .grab_mode      = CAMERA_GRAB_WHEN_EMPTY,
};

void OV7725_ESP32_Init(void)
{
    esp_err_t err = esp_camera_init(&camera_config);
    if (err != ESP_OK) {
        printf("OV7725 init fail: 0x%x\n", err);
        return;
    }

    sensor_t *s = esp_camera_sensor_get();
    s->set_framesize(s, FRAMESIZE_VGA);
    s->set_pixformat(s, PIXFORMAT_RGB565);
    s->set_vflip(s, 0);
    s->set_hmirror(s, 0);
    printf("OV7725 ESP32 就绪, 60fps VGA\n");
}
```

---

## 七、常见问题

| 问题 | 解决方案 |
|------|---------|
| 帧率不到60fps | 检查PLL和PCLK分频,确认0x11配置 |
| 低照度噪点 | OV7725大像素低照度好,检查AGC增益上限 |
| SCCB无应答 | 检查I2C地址0x42 |
| 图像偏暗 | 调整AEC目标寄存器0x25 |

参考资料

暂无参考文献