OV2640是OmniVision公司生产的一颗1/4寸的CMOS UXGA(1632*1232)图像传感器;
支持自动曝光控制、自动增益控制、自动白平衡、自动消除灯光条纹等自动控制功能。
UXGA最高15帧/秒,SVGA可达30帧,CIF可达60帧;
支持图像压缩,即可输出JPEG图像数据.
OV2640 传感器采用 BGA 封装,它的前端是采光窗口,引脚都在背面引出。
管脚名称 |
管脚类型 |
管脚描述 |
OV_SCL |
输入 |
SCCB总线的时钟线,可类比I2C的SCL |
OV_SDA |
I/O |
SCCB总线的数据线,可类比I2C的SDA |
RESETB |
输入 |
系统复位管脚,低电平有效 |
PWDN |
输入 |
掉电/省电模式,高电平有效 |
HREF |
输出 |
行同步信号 |
VSYNC |
输出 |
帧同步信号 |
PCLK |
输出 |
像素同步时钟输出信号 |
XCLK |
输入 |
外部时钟输入端口,可接外部晶振 |
D0…D7 |
输出 |
像素数据输出端口 |
UXGA:分辨率为1600*1200的输出格式
SXGA:分辨率为1280*1024输出格式
VGA:分辨率为640*480的输出模式
QVGA:分辨率为320*240的输出格式
QQVGA:分辨率为160*120的输出格式
SVGA:分辨率为800*600的输出格式
VGA:分辨率为640*480的输出格式
系统上电后,MCU配置OV2640的工作方式,在OV2640准备好图像后,VSYNC会被拉高一段时间,在此时间内MCU通过PCLK上升沿中断按字节接收图像数据。帧同步信号-摄像头开始发送一帧图像(如320x160个像素)时发出的信号。像素同步信号则是开始发送一个像素点时发出的信号。
若图像格式设置为 RGB565,两个字节传输一个RGB像素数据,进行数据输出时,D0-D7 数据线在 PCLK 在上升沿阶段维持稳定,并且会在 1 个像素同步时钟 PCLK 的驱动下发送 1 字节的数据信号,所以 2 个 PCLK 时钟可发送 1 个 RGB565 格式的像素数据。当 HREF 为高电平时,像素数据依次传输,每传输完一行数据时,行同步信号HREF 会输出一个电平跳变信号间隔开当前行和下一行的数据;一帧的图像由 N 行数据组 成,当 VSYNC 为低电平时,各行的像素数据依次传输,每传输完一帧图像时,VSYNC 会输出一个电平跳变信号。
通过SSCB初始化摄像模块(初始化上百个寄存器)
等待帧同步信号VSYNC上升沿,开始读取一帧的数据
在此过程中VSYNC保持高电平,每个像素同步信号PCLK下降沿,开始读走8位数据线的数据(1像素),重复n次
直到帧同步信号VSYNC下降沿,一帧图像数据读取结束
等待帧同步信号VSYNC上升沿,开始读取新一帧的数据
SCCB(Serial Camera Control Bus) 串行摄像机控制总线协议,对 OV2640 寄存器的配置参数是通过 SCCB 总线传输过去的,而 SCCB 总线跟 I2C 十分类似,所以在 STM32 驱动中可以直接使用片上 I2C 外设与它通讯。SCCB 的起始信号、停止信号及数据有效性与 I2C 完全一样
起始信号:在 SCL(图中为 SIO_C)为高电平时,SDA(图中为 SIO_D)出现一个下降沿,则 SCCB 开始传输。
停止信号:在 SCL 为高电平时,SDA 出现一个上升沿,则 SCCB 停止传输。
数据有效性:除了开始和停止状态,在数据传输过程中,当 SCL 为高电平时,必须保证SDA 上的数据稳定,也就是说,SDA 上的电平变换只能发生在 SCL 为低电平的时候,SDA 的信号在 SCL 为高电平时被采集。
SCCB 特性都与 I2C 无区别,完全可以使用 STM32 的 I2C 外设 来与 OV2640 进行 SCCB 通讯。
void OV2640_CaptureGpioInit(void)
{
RCC->APB2ENR|=1<<4;
GPIOC->CRL = 0x88888888;
GPIOC->ODR |= 0x00FF;
/* 初始化VSYNC连接引脚为上升沿中断 */
Exit_Init(GPIOB, GPIO_Pin_8, GPIO_Mode_IPU, EXTI_Trigger_Rising_Falling, 2, 5); //VSYNC
/* 初始化PCLK连接引脚为下降沿中断 */
Exit_Init(GPIOB, GPIO_Pin_15, GPIO_Mode_IPU, EXTI_Trigger_Falling, 2, 4);//PCLK
GpioInit(GPIOB, GPIO_Pin_14, GPIO_Mode_IPU, (GPIOSpeed_TypeDef)0);
}
u8 JpegBuffer[10240];
u32 JpegDataCnt = 0;
u8 VsyncActive = 0;
//VSYNC触发中断
void EXTI9_5_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line8); //清除中断标志位
GPIOA->ODR ^= (1 << 0); //LED闪烁一次
if(GPIOB->IDR & (1<< 8))//PB8连接VSYNC
{
EXTI->IMR |= EXTI_Line15; //使能像素同步
EXTI->EMR |= EXTI_Line15;
VsyncActive = 1;
}
else
{
EXTI->IMR &= ~EXTI_Line15; //关闭像素同步
EXTI->EMR &= ~EXTI_Line15;
if(VsyncActive == 1)
{ //第二次进入帧同步信号中断,一帧数据传输完毕
VsyncActive = 2;
EXTI->IMR &= ~EXTI_Line8; //关闭帧同步中断
EXTI->EMR &= ~EXTI_Line8;
}
else
{
VsyncActive = 0;
}
}
}
//PCLK触发中断
void EXTI15_10_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line15); //清除中断标志位
JpegBuffer[JpegDataCnt++] = (u8)(GPIOC->IDR); //PC0~PC7与D0~D7相连,存储数据
}
while(1)
{
if(VsyncActive == 2)
{
for(i = 0; i < JpegDataCnt; i ++)
{
USART_Transmit(JpegBuffer[i]);
}
JpegDataCnt = 0; //传输完一帧图像,JPEG重新计数
EXTI->IMR |= EXTI_Line8; //使能帧同步信号中断
EXTI->EMR |= EXTI_Line8;
}
}