基于FPGA的OV7670摄像头实时检测

本文详细介绍了基于FPGA实现OV7670摄像头的数据捕获及VGA显示的系统设计,涵盖了OV7670摄像头的初始化配置、SCCB协议、DVP协议、FIFO控制以及SDRAM和VGA接口的处理。系统通过FPGA从OV7670接收图像数据,经过转换和缓存后,存储到SDRAM,再通过VGA接口实时显示。整个流程包括时钟模块、初始化模块、数据流处理、FIFO模块以及VGA控制模块。

目录

前言:整体系统框图

一、OV7670摄像头简介

二、OV7670 SCCB协议简介

三、OV7670初始化寄存器配置

四、OV7670初始化代码编写

 五、什么是DVP?

六、摄像头写数据请求

七、顶层文件编写

八、效果


前言:整体系统框图

 如图所示,FPGA中主要模块包含:时钟模块、OV7670初始化模块、DVP协议数据流模块、写FIFO模块、写FIFO控制模块、SDRAM控制模块、读FIFO模块、读FIFO控制模块、VGA控制模块。

其整体流程为:启动时先对摄像头进行初始化设置,初始化完成后,FPGA从摄像头获取一帧一帧的图像数据,根据数据手册将ov7670数据流转换成我们需要的RGB565数据流,随后存入写FIFO模块;(写控制模块)当写FIFO模块中存储的数据大于等于8时,发出SDRAM写请求,SDRAM写请求通过后,读取FIFO数据存储起来;(读FIFO模块)当读FIFO数据小于等于8时,读取SDRAM中的数据经过读FIFO缓存后送入VGA显示模块进行显示。同时写控制模块和读控制模块控制SDRAM读写地址的增加。

1、时钟模块
     这里使用PLL的IP核,以50MHz时钟生成25MHz和100MHz时钟,其中摄像头初始化模块和VGA控制模块使用的是25MHz,SDRAM控制模块、写FIFO控制模块和读FIFO控制模块使用的是100MHz,写FIFO和读FIFO模块都是异步FIFO,使用25MHz和100MHz时钟。

一、OV7670摄像头简介

OV7670/OV7171 图像传感器,体积小、工作电压低,提供单片VGA摄像头和影像处理器的所有功能。通过SCCB 总线控制,可以输出整帧、子采样、取窗口等方式的各种分辨率8位影响数据。该产品VGA图像最高达到30帧/秒。用户可以完全控制图像质量、数据格式和传输方式。所有图像处理功能过程包括伽玛曲线、白平衡、饱和度、色度等都可以通过SCCB接口编程。OmmiVision 图像传感器应用独有的传感器技术,通过减少或消除光学或电子缺陷如固定图案噪声、托尾、浮散等,提高图像质量,得到清晰的稳定的彩色图像。

主要引出的信号引脚如下:

3.3V--输入电源电压(推荐使用3.3V,5V也可,但不推荐)

GND

SCL(SIOC):SCCB时钟口(注意:部分单片机需要上拉控制,和I2C接口类似)

SDA(SIOD):SCCB数据口(注意:部分单片机需要上拉控制,和I2C接口类似)

VSYNC:场同步(帧同步)信号(输出信号)

HREF:行同步信号(输出信号,一般可以不使用,特殊情况使用)

PCLK:像素时钟

XCLK:系统时钟输入

D0-D7:数据位(输出信号)

RESET:初始化所有寄存器到默认值 0:RESET 模式 1:一般模式

PWDN:POWER DOWN模式选择 0:工作 1:POWER DOWN

其中,对OV7670初始化配置只使用SCL和SDA两个信号线。

所用模块如图:

二、OV7670 SCCB协议简介

      对OV7670初始化使用的是SCCB协议,由数据线SDA和时钟线SCL组成,SCCB协议和I2C协议基本一样,是简化的I2C协议,前面博客中已经讲过I2C协议,需要可以去看看。

SCCB(SeriaI Camera ControlBus)是简化的I2C协议,SIO-l是串行时钟输入线,SIO-O是串行双向数据线,分别相当于I2C协议的SCL和SDA。SCCB的总线时序与I2C基本相同,它的响应信号ACK被称为一个传输单元的第9位,分为Don’t care和NA。Don’t care位由从机产生;NA位由主机产生,由于SCCB不支持多字节的读写,NA位必须为高电平。另外,SCCB没有重复起始的概念,因此在SCCB的读周期中,当主机发送完片内寄存器地址后,必须发送总线停止条件。不然在发送读命令时,从机将不能产生Don’t care响应信号。

这里采用的是100KHz的SCL。

三、OV7670初始化寄存器配置

     OV7670摄像头共201个寄存器,需要配置的有一百六十几个,这个具体看数据手册吧,下边代码中会有配置寄存器的数据。

四、OV7670初始化代码编写

`timescale 1 ns / 1 ns
module system_ctrl
(
	input 		clk,		//50MHz
	input 		rst_n,		//global reset

	output 		sys_rst_n,	//system reset
	output 		clk_c0,		
	output 		clk_c1,
	output		clk_c2,	//-75deg
	output		clk_c3	//-75deg
);

//----------------------------------------------
//rst_n synchronism, is controlled by the input clk
reg     rst_nr1,rst_nr2;
always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		rst_nr1 <= 1'b0;
		rst_nr2 <= 1'b0;
		end
	else
		begin
		rst_nr1 <= 1'b1;
		rst_nr2 <= rst_nr1;
		end
end

//----------------------------------
//component instantiation for system_delay
wire	delay_done;
system_delay	u_system_delay
(
	.clk		(clk),
	.rst_n		(rst_nr2),
	.delay_done	(delay_done)
);
wire	pll_rst = ~rst_nr2 & ~delay_done;	//active High

//----------------------------------------------
//Component instantiation
wire 	locked;	
sdram_pll	u_sdram_pll
(
	.inclk0	(clk),
	.areset	(pll_rst),
	.locked	(locked),
			
	.c0		(clk_c0),
	.c1		(clk_c1),
	.c2		(clk_c2),
	.c3		(clk_c3)
);



//----------------------------------------------
//sys_rst_n synchronism, is control by the highest output clk
  
wire	sysrst_nr0 = rst_nr2 & locked & delay_done;  
reg 	sysrst_nr1, sysrst_nr2; 
always @(posedge clk_c1 or negedge sysrst_nr0)
begin
	if(!sysrst_nr0) 
        begin
        sysrst_nr1 <= 1'b0;
        sysrst_nr2 <= 1'b0;
        end        
	else 
        begin
        sysrst_nr1 <= 1'b1;
        sysrst_nr2 <= sysrst_nr1;
        end
end
assign sys_rst_n = sysrst_nr2;	//active Low

endmodule

//################################################//
//################################################//

module system_delay
(
	input	clk,		//50MHz
	input	rst_n,
	output	delay_done
);

//------------------------------------------
// Delay 100ms for steady state
localparam	DELAY_CNT = 23'd100_0000;	//50ms
reg	[22:0] cnt;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		cnt <= 0;
	else
		begin
		if(cnt < DELAY_CNT) //1ms
			cnt <= cnt + 1'b1;
		else
			cnt <= cnt;
		end
end

//------------------------------------------
//sys_rst_n synchronism
assign	delay_done = (cnt == DELAY_CNT)? 1'b1 : 1'b0;

endmodule

摄像头检测代码

`timescale 1ns/1ns
module CMOS_Capture
(
	//Global Clock
	input				iCLK,			//25MHz
	input				iRST_N,

	//I2C Initilize Done
	input				Init_Done,		//Init Done
	
	//Sensor Interface
	output				CMOS_RST_N,		//cmos work state(5ms delay for sccb config)
	output				CMOS_PWDN,      //cmos power on	
	output				CMOS_XCLK,		//25MHz
	input				CMOS_PCLK,		//25MHz
	input	[7:0]		CMOS_iDATA,		//CMOS Data
	input				CMOS_VSYNC,		//L: Vaild
	i
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值