介绍
OmniVision OV7725 VGA(640x480) CMOS图像传感器,主打高速和低照度性能,支持60fps@VGA。内部时钟版本集成PLL,仅需单一参考时钟。广泛应用于无人机、机器人视觉、工业检测等需要高速低延迟的场景。
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 内部时钟版本驱动代码例程
## 一、平台说明
- **主控平台**: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, ®, 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 |
暂无参考文献