前言

链接:https://pan.baidu.com/s/1hmWm1w8Ny4Il25DIFR74Jw?pwd=1234
提取码:1234


OV5640_V5是豪威科技生产的500W像素的CMOS图像传感器,最高支持26241964分辨率(物理尺寸),对应25921944(图像尺寸)。输出支持DVP接口,控制接口为标准的SCCB接口(兼容IIC)。

同时OV5640摄像头支持输出2592x1944分辨率以下任意分辨率的图像。
在这里插入图片描述

  • ISP的输入窗口(物理像素区域)通过0x3800-0x3807等8个寄存器配置。
  • 预缩放窗口设置通过0x3810-0x3813寄存器配置。
  • 图像输出帧率通过0x3035 - 0x3037寄存器配置。其中设置0x3035寄存器值为0x21,输出帧率30fps。

在这里插入图片描述

OV5640参数和内部结构

产品参数:
在这里插入图片描述
在这里插入图片描述
支持输出的图像格式:
在这里插入图片描述

如下是OV5640摄像头的内部结构框图
在这里插入图片描述

内部结构复杂,同时也不是FPGA图像采集的重点,我们将重点放在输出接口上。
首先摄像头采集图像数据,经过内部一系列的处理(放大、数字信号转换等),最终通过DVP端口输出,DVP本身拥有10位数据线,因此可输出10位RAW数据,但大多数情况下,使用8位数据线来输出RGB888及RGB565等格式,因此我们取高8位即可,舍弃掉了低2位。

SCCB接口

OV5640采用16位(两个字节)表示寄存器地址,器件地址 7‘h3c
如下为SCCB写寄存器的示意图,
在这里插入图片描述

DVP接口帧时序

类似于VGA的行场同步信号,这里先不多介绍。

分析像素时钟pclk:
在这里插入图片描述
PCLK像素时钟:一个像素时钟输出一个像素(10位/8位),由于采用8位接口输出,那么每一个工作时钟pclk输出一个字节,对于RGB565格式来说,一个像素是16位,两个字节,所以花费两个像素时钟pclk才能输出一个16位的像素,具体的16位数据中,哪几位表示红色绿色蓝色分量,也是通过寄存器配置。

这里到底像素时钟是多少,有分歧,有比较熟悉这块的大佬可以下面留言讨论。但是可以知道的是:PCLK是 OV5640输出数据时的同步信号,它是由 OV5640 输出的信号。
而XCLK为工作时钟,可以外接晶振或由外部控制器提供。

但是如果真的需要手动计算像素时钟那么公式如下

因此这里对于DVP 640 * 480 * 30fps标准来说,像素时钟的求解方式 : 物理分辨率 * 帧率 = 784 * 510 * 30 = 12Mhz

分析帧时序:

Vsync: 帧同步信号,高电平期间,输出一帧图像数据。
Hsyn/Href:行同步信号,高电平期间输出一行图像数据。
在这里插入图片描述
DVP接口时序参数,和VGA类似,在OV5640官方数据手册中根据输出图像分辨率查看各部分的时序参数即可。

硬件电路

如下是OV5640模块接口原理图:
18引脚应该是OV5640的工作时钟,但是由于默认输入工作时钟Xclk = 24Mhz,因此18引脚为NC。
在这里插入图片描述
注意:OV5640 芯片的 DVP 接口本身拥有 10 位的数据线,可以输出 10 位的 RAW 数据,但是在大多数情况下我们使用的数据是八位的,因此只要DVP输出接口的高 8 位数据即可,因此只保留D[9:2],映射到接口OV-D0-7。

注意:上述电路的 OV_SCL 和 OV_SDA 没有连接物理上拉电阻,直接使用会出现问题,因此必须在Quartus II
软件的引脚配置中对这两处开启 FPGA 的 IO 片上上拉电阻,才能正常使用。

引脚解释如下:
OV5640的24Mhz工作时钟是由FPGA的PLL提供的,然后摄像头内部有自己的PLL,即可按照内部设计供给其内部各个模块使用,使得摄像头能正常工作。
在这里插入图片描述

OV5640上电控制

OV5640上电时序:
其中DOVDD和AVDD器件自带,无需自己设计
在这里插入图片描述

  • 由于ov5640_pwdn信号的高电平掉电使能,可以不延迟,直接赋0。
  • ov5640_rst_n低电平复位,必须至少延迟1ms后才能拉高。
  • ov5640_rst_n拉高后再延时 20ms 后才能进行 SCCB 配置

OV5640上电控制的Verilog代码

module power_ctrl    (   //OV5640上电控制
	
	
	input                  clk                     , // 50MHz
	input                  rst_n                   ,
	
	output                 ov5640_pwdn             , // ov5640掉电使能
	output                 ov5640_rst_n            , // ov5640复位
	output                 power_done              ,   // power_ctrl全面有效,相当于上电完成信号标志,SCCB可以开始工作
	
	output reg     [18:0]  cnt_6ms                 ,
	output reg     [16:0]  cnt_2ms                 ,
	output reg     [20:0]  cnt_21ms                //1050000刚好可以用21位二进制表示
	);
	
	localparam T2_6MS     = 30_0000   ; // T2>=5ms取6ms,6ms=1000000ns,计数次数:1000000ns/20ns = 300000
	localparam T3_2MS     = 10_0000   ; // T3>=1ms取2ms
	localparam T4_21MS    = 105_0000  ; // T4>=20ms取21ms
	
//ov5640_pwdn掉电使能的设计,要求至少延迟5ms才能拉低,取6ms,另外也可直接将ov5640_pwdn赋值低电平0
//设计6ms计数器	
	always @(posedge clk or negedge rst_n) begin
	    if(!rst_n) 
	        cnt_6ms <= 0;
	    else if(ov5640_pwdn == 1'b1) begin //高电平掉电的时候计数
			  cnt_6ms <= cnt_6ms + 1'b1;
	    end
		 else
		    cnt_6ms <= cnt_6ms;
	end
	
//当计数值大于等于6ms的时候,ov5640_pwdn赋值低电平。	
	assign ov5640_pwdn = (cnt_6ms >= T2_6MS) ? 1'b0 : 1'b1;
	
//ov5640_rst_n复位信号的设计,该信号至少延迟1ms,这里取2ms
	
	always @(posedge clk or negedge rst_n) begin
	    if(!rst_n) begin
	        cnt_2ms <= 'd0;
	    end
	    else if(ov5640_rst_n == 1'b0 && ov5640_pwdn == 1'b0) begin    //相当于从还没开始复位以及上电使能信号刚来的时候开始进行2ms的计数
	        cnt_2ms <= cnt_2ms + 1'b1;
	    end
	end
//低电平复位	
	assign ov5640_rst_n = (cnt_2ms >= T3_2MS) ? 1'b1 : 1'b0;

//power_done  上电完成的设计,要求是复位被拉高后,延迟至少20ms,才可进行SCCB/IIC配置,取21ms

	always  @(posedge clk or negedge rst_n) begin
	    if(!rst_n) begin
	        cnt_21ms <= 'd0;
	    end
	    else if(power_done == 1'b0 && ov5640_rst_n == 1'b1) begin    //上电还没完成且处于工作状态,就开始进行21ms的计数
	        cnt_21ms <= cnt_21ms + 1'b1;
	    end
		 else 
		      cnt_21ms <= cnt_21ms ;
	end
	
	
	assign power_done = (cnt_21ms >= T4_21MS) ? 1'b1 : 1'b0; //上电完成的标志:如果计数大于或者等于21ms的时候就代表上电完成
		
endmodule
	

tb仿真:

`timescale 1ns/1ns //时间精度
`define clock_period 20 //时间周期

module power_ctrl_tb;

			reg     clk  ; // 50MHz
			reg     rst_n;

		   wire    ov5640_pwdn ; // ov5640掉电使能
		   wire    ov5640_rst_n; // ov5640复位
		   wire    power_done ;
		   wire   [18:0]    cnt_6ms;  
         wire   [16:0]    cnt_2ms ;
		   wire   [20:0]   cnt_21ms;
		  
power_ctrl u1(
         
			.clk(clk),         
			.rst_n(rst_n),       
			.ov5640_pwdn(ov5640_pwdn), 
			.ov5640_rst_n(ov5640_rst_n),
			.power_done (power_done),
			.cnt_6ms(cnt_6ms), 
         .cnt_2ms(cnt_2ms),
         .cnt_21ms(cnt_21ms)
);   

initial		
    clk = 0;
always #(`clock_period/2) clk= ~clk;

initial begin
   rst_n=0; 
	#(`clock_period*5);
   rst_n=1;
	#1000000000;
	$stop;
end	

endmodule

如下是仿真波形图:
在这里插入图片描述
通过时间节点可看到,6ms的时候掉电使能有效,变成低电平,然后再延迟2ms,复位信号被拉高,然后再延迟21ms才能进行SCCB的配置,设计符合要求。


常用的摄像头还有OV7670、OV7725,各方面的时序与OV5640都是一致的,只是上电配置不同。


如有错误,请指正!

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐