🎉欢迎来到FPGA专栏~基于FPGA的RGB摄像头实验
一、效果演示
来自于小梅哥【学习资料】:
数字图像处理是指将图像信号转换成数字信号并利用计算机对其进行处理的过程。图像处理最早出现于20世纪50年代,当时的电子计算机已经发展到一定水平,人们开始利用计算机来处理图形和图像信息。数字图像处理作为一门学科大约形成于20世纪60年代初期。早期的图像处理的目的是改善图像的质量,它以人为对象,以改善人的视觉效果为目的。图像处理中,输入的是质量低的图像,输出的是改善质量后的图像,常用的图像处理方法有图像增强、复原、编码、压缩等。
数字图像处理常用方法有以下几种:
1、图像变换
2、图像编码压缩
3、图像增强和复原
4、图像分割
5、图像描述
6、图像分类(识别)
二、项目说明
该系列文章只是作为学习记录,并无其余用途。所发文章内容是经过自己本身操作和记录整理得来。
本篇文章记录基于ACM68013模块的OV5640 RGB摄像头实验。
🥝项目资料获取
该项目资料获取:基于ACM68013模块的OV5640 RGB摄像头实验
项目资料详细内容:
ACM68013模块资料:
🥝实验硬件
本次文章中所使用到的硬件为:AC620V2开发板、ACM68013模块和OV5640摄像头模块。
实验所需硬件如下图所示:
❤️特别鸣谢:小梅哥FPGA
📜硬件购买链接及详细介绍:
🔸【FPGA】USB2.0高速通信模块:ACM68013模块
🔸【FPGA】OV5640高清摄像头模块:OV5640摄像头模块🔸更多资料和模块请前往淘宝店铺:小梅哥FPGA
🥝项目分析
系统整体设计如下图所示(来自于项目资料中的PDF文档):
以下是资料中对于各部分作用的介绍:
- PLL模块:锁相环模块,生成本次实验每个模块所需要的工作时钟,其中输入时钟为 50M 的系统时钟,由开发板上的晶振提供,输出 24M 的时钟给到摄像头模块使用,输出 50M 的时钟给其他模块使用。
- usb_stream_out 模块:USB 数据流发送控制模块,不断的将端点 2 中的数据读取出来,数据读取后直接作为端口输出。
- usb_cmd 模块:接收转命令模块,对 USB 接收到的数据进行分析,提取出每个控制命令帧。
- usb_cmd_rx 模块:指令转控制模块,将从接收转命令模块接收到的数据转换为相应的控制 USB 启动传输的信号。
- camera_init 模块:摄像头初始化模块,完成对 OV5640 众多模式设置寄存器的写入操作。
- DVP_Capture 模块:实现每两个数据拼接为 1 个 16 位的数据并按照写RAM 或 FIFO 的接口形式输出。
- usb_send_ctrl模块:USB数据输出控制模块,控制 USB 启动传输和USB FIFO 的清除工作。
- usb_stream_in模块:USB数据流发送模块,将采集到的数据通过USB发送出去。
其中,模块fx2_stream_in_ov5640的内容为:
/
// Module Name : fx2_stream_in_ov5640
// Description : 摄像头采集,USB发送
/
module fx2_stream_in_ov5640(
//System clock reset
input clk50m , //系统时钟输入,50MHz
input reset_n , //复位信号输入
//usb interface
output fx2_clear , //连接USB模块的PA0
usb_ctrl
inout [15:0]fx2_fdata ,
input fx2_flagb ,
input fx2_flagc ,
input fx2_ifclk ,
output [1:0]fx2_faddr ,
output fx2_sloe ,
output fx2_slwr ,
output fx2_slrd ,
output fx2_pkt_end ,
output fx2_slcs ,
//camera interface
output camera_sclk ,
inout camera_sdat ,
input camera_vsync ,
input camera_href ,
input camera_pclk ,
output camera_xclk ,
input [7:0]camera_data ,
output camera_rst_n ,
output camera_pwdn ,
//led
output [1:0]led
);
//*****************************
//Set IMAGE Size
parameter IMAGE_WIDTH = 800;
parameter IMAGE_HEIGHT = 480;
//*****************************
//clock
wire pll_locked;
wire loc_clk50m;
wire loc_clk24m;
//reset
wire g_rst_p;
//camera interface
wire camera_init_done;
wire pclk_bufg_o;
wire [15:0] image_data;
wire image_data_valid;
wire image_data_hs;
wire image_data_vs;
wire [11:0] image_data_xaddr;
wire [11:0] image_data_yaddr;
reg pixel_data_valid;
reg [15:0] pixel_data;
//USB Ctrl
wire [1:0]fx2_faddr0;//FX2型USB2.0芯片的SlaveFIFO的FIFO地址线
wire fx2_slrd0;//FX2型USB2.0芯片的SlaveFIFO的读控制信号,低电平有效
wire fx2_slwr0;//FX2型USB2.0芯片的SlaveFIFO的写控制信号,低电平有效
wire fx2_sloe0;//FX2型USB2.0芯片的SlaveFIFO的输出使能信号,低电平有效
wire fx2_flagc0;//FX2型USB2.0芯片的端点6满标志
wire fx2_flagb0; //FX2型USB2.0芯片的端点2空标志
wire fx2_pkt_end0;//数据包结束标志信号
wire fx2_slcs0;
wire [15:0]fx2_fdata1;
wire [1:0]fx2_faddr1;//FX2型USB2.0芯片的SlaveFIFO的FIFO地址线
wire fx2_slrd1;//FX2型USB2.0芯片的SlaveFIFO的读控制信号,低电平有效
wire fx2_slwr1;//FX2型USB2.0芯片的SlaveFIFO的写控制信号,低电平有效
wire fx2_sloe1;//FX2型USB2.0芯片的SlaveFIFO的输出使能信号,低电平有效
wire fx2_flagc1;//FX2型USB2.0芯片的端点6满标志
wire fx2_flagb1;//FX2型USB2.0芯片的端点2空标志
wire fx2_pkt_end1;//数据包结束标志信号
wire fx2_slcs1;
wire inout_switch;
//0: read由pc向FPGA下发指令 1:write由FPGA向fx2芯片继而向pc上传数据
wire rw_switch;
wire usb_fifo_full;
wire usb_fifo_wrempty;
wire [15:0] usb_fifo_wrdata;
wire usb_fifo_wrreq;
wire [10:0] usb_fifo_usedw;
assign rw_switch = (inout_switch || (usb_fifo_wrempty == 0 ))?1'd1:1'd0;
//inout_switch为1是rw_switch为1的充分条件,
//如果usb_fifo_wrempty没有为1,
//说明usbfifo还没有读完,需要再给它一点读完的时间直到收到它为0的反馈
assign fx2_fdata=rw_switch? fx2_fdata1 : 16'dz;
assign fx2_faddr=rw_switch ? fx2_faddr1 : fx2_faddr0;
assign fx2_sloe=rw_switch ? fx2_sloe1 : fx2_sloe0;
assign fx2_slwr=rw_switch ? fx2_slwr1 : fx2_slwr0;
assign fx2_slrd=rw_switch ? fx2_slrd1 : fx2_slrd0;
assign fx2_pkt_end=rw_switch ? fx2_pkt_end1 : fx2_pkt_end0;
assign fx2_slcs=rw_switch ? fx2_slcs1 : fx2_slcs0;
assign led = {~camera_init_done,~pll_locked};
pll pll (
.areset(~reset_n),
.inclk0(clk50m),
.c0(loc_clk50m),
.c1(loc_clk24m),
.locked(pll_locked)
);
wire [15:0]usb_data_out;
wire usb_data_valid;
//USB数据流发送控制模块:不断的将端点2中的数据读取出来,数据读取后直接作为端口输出
usb_stream_out usb_stream_out(
.clk (loc_clk50m),
.fx2_fdata (fx2_fdata), // FX2型USB2.0芯片的SlaveFIFO的数据线
.fx2_faddr (fx2_faddr0), // FX2型USB2.0芯片的SlaveFIFO的FIFO地址线
.fx2_slrd (fx2_slrd0), // FX2型USB2.0芯片的SlaveFIFO的读控制信号,低电平有效
.fx2_slwr (fx2_slwr0), // FX2型USB2.0芯片的SlaveFIFO的写控制信号,低电平有效
.fx2_sloe (fx2_sloe0), // FX2型USB2.0芯片的SlaveFIFO的输出使能信号,低电平有效
.fx2_flagc (fx2_flagc ), // FX2型USB2.0芯片的端点6满标志
.fx2_flagb (fx2_flagb ), // FX2型USB2.0芯片的端点2空标志
.fx2_ifclk (fx2_ifclk ), // FX2型USB2.0芯片的接口时钟信号
.fx2_pkt_end (fx2_pkt_end0), //数据包结束标志信号
.fx2_slcs (fx2_slcs0),
.reset_n (reset_n),
.data_out (usb_data_out),
//经过FPGA接收了的USB数据.这个数据从pc经过fx2芯片提供给FPGA
.data_valid (usb_data_valid),
//经过FPGA接收了的USB数据有效标志信号.FPGA只要在读数据,这个信号一直拉高输出给FX2
.source_ready (~rw_switch)
//外部数据消费者数据接收允许信号,例如FPGA中的缓存FIFO中有足够的空间存储一帧USB数据,则允许从Slave FIFO中去读取数据。当FPGA有能力读取一帧数据,则向外
);
wire [7:0]cmd_addr;
wire [31:0]cmd_data;
wire cmdvalid;
下方模块对接收的信号进行解析,输出地址、数据、有效,然后通过地址判断这个数据是采样起始信号,采样数量,还是采样通道
usb_cmd usb_cmd_inst(
.Clk (fx2_ifclk),
.Reset_n (reset_n),
.rx_data (usb_data_out),
.rx_done (usb_data_valid),
.address (cmd_addr),
.data (cmd_data),
.cmdvalid (cmdvalid)
);
wire start_sample;
//命令解析函数
usb_cmd_rx usb_cmd_rx(
.clk(fx2_ifclk),
.reset_n(reset_n),
.cmdvalid(cmdvalid),
.cmd_addr(cmd_addr),
.cmd_data(cmd_data),
.start_sample(start_sample)
);
assign camera_xclk = loc_clk24m;
camera_init
#(
.SYS_CLOCK ( 50_000_000 ),//系统时钟采用50MHz
.SCL_CLOCK ( 400_000 ),//SCL总线时钟采用400kHz
.CAMERA_TYPE ( "ov5640" ),//"ov5640" or "ov7725"
.IMAGE_TYPE ( 0 ),// 0: RGB; 1: JPEG
.IMAGE_WIDTH ( IMAGE_WIDTH ),// 图片宽度
.IMAGE_HEIGHT ( IMAGE_HEIGHT ),// 图片高度
.IMAGE_FLIP_EN ( 0 ),// 0: 不翻转,1: 上下翻转
.IMAGE_MIRROR_EN( 0 ) // 0: 不镜像,1: 左右镜像
)camera_init
(
.Clk (loc_clk50m ),
.Rst_n (reset_n ),
.Init_Done (camera_init_done ),
.camera_rst_n(camera_rst_n ),
.camera_pwdn (camera_pwdn ),
.i2c_sclk (camera_sclk ),
.i2c_sdat (camera_sdat )
);
assign pclk_bufg_o = camera_pclk;
wire ImageState;
DVP_Capture DVP_Capture(
.Rst_n (reset_n ),//input
.PCLK (pclk_bufg_o ),//input
.Vsync (camera_vsync ),//input
.Href (camera_href ),//input
.Data (camera_data ),//input [7:0]
.ImageState (ImageState ),//output reg
.DataValid (image_data_valid ),//output
.DataPixel (image_data ),//output [15:0]
.DataHs (image_data_hs ),//output
.DataVs (image_data_vs ),//output
.Xaddr (image_data_xaddr ),//output [11:0],start is 1
.Yaddr (image_data_yaddr ) //output [11:0],start is 1
);
reg[4:0] start_sample_r;
always@(posedge fx2_ifclk)
begin
start_sample_r <= {start_sample_r[3:0],start_sample}; //拓宽start_sample信号,确保能收到启动开始信号,使摄像头的数据通过USB进行传输
end
reg image_data_vs_dly1;
reg [15:0] image_data_dly1;
reg image_data_valid_dly1;
always@(posedge pclk_bufg_o)
begin
image_data_vs_dly1 <= image_data_vs;
image_data_dly1 <= image_data;
image_data_valid_dly1 <= image_data_valid;
end
usb_send_ctrl usb_send_ctrl
(
.reset_n (reset_n) ,
.clk (pclk_bufg_o) , //pclk_bufg_o
.data_i (image_data_dly1),
.data_valid_i (image_data_valid_dly1) ,
.start_sample (|start_sample_r) , //按位或,只要检测到start_sample_r中某一时刻得到start_sample信号就启动传输
.camera_vs_start (~image_data_vs_dly1 && image_data_vs),
.usb_fifo_full (usb_fifo_full),
.inout_switch (inout_switch) ,
.usb_fifo_wrreq (usb_fifo_wrreq) , //USB FIFO的写请求信号,产生该信号,USB开始发送数据
.fx2_clear (fx2_clear) ,//USB清除
.usb_fifo_wrdata (usb_fifo_wrdata) //USB需要发送的数据
);
//USB数据流发送控制模块
usb_stream_in usb_stream_in(
.reset_n (reset_n),
.fx2_fdata (fx2_fdata1), //FX2型USB2.0芯片的SlaveFIFO的数据线
.fx2_faddr (fx2_faddr1), //FX2型USB2.0芯片的SlaveFIFO的FIFO地址线
.fx2_slrd (fx2_slrd1), //FX2型USB2.0芯片的SlaveFIFO的读控制信号,低电平有效
.fx2_slwr (fx2_slwr1), //FX2型USB2.0芯片的SlaveFIFO的写控制信号,低电平有效
.fx2_sloe (fx2_sloe1), //FX2型USB2.0芯片的SlaveFIFO的输出使能信号,低电平有效
.fx2_flagc (fx2_flagc), //FX2型USB2.0芯片的端点6满标志
.fx2_flagb (fx2_flagb), //FX2型USB2.0芯片的端点2空标志
.fx2_ifclk (fx2_ifclk), //FX2型USB2.0芯片的接口时钟信号
.fx2_pkt_end (fx2_pkt_end1), //数据包结束标志信号
.fx2_slcs (fx2_slcs1),
.usb_fifo_wrclk (pclk_bufg_o),
.usb_fifo_wrdata(usb_fifo_wrdata),
.usb_fifo_full(usb_fifo_full),
.usb_fifo_wrreq (usb_fifo_wrreq),
.usb_fifo_usedw (usb_fifo_usedw),
.usb_fifo_wrempty(usb_fifo_wrempty),
.usb_fifo_rst(fx2_clear)
);
endmodule
三、过程记录
🍋搭建硬件
将ACM68013模块和OV5640摄像头模块按照AC620V2开发板的对应位置接好,如图所示:
🍋程序烧录
AC620V2开发板程序烧录JIC文件:
开发板上的 LED0 和 LED1 点亮。LED0 被点亮说明 PLL 锁相环工作正常;LED1 被点亮说明摄像头初始化完成。
ACM68013模块烧写固件, 烧写文件夹下的“slave_for_adc.iic”
文件至EEPROM中:
🍋注意事项
相关内容在盘A_AC620V2开发板标准配套资料\01_教材文档\02A文件中查看。
对ACM68013模块与电脑连接的问题,未识别该模块:
正确安装好对应的驱动之后:
在设备管理器中看到设备名称:
🍋结果显示
通过小梅哥USB摄像头上位机显示结果:
🧸结尾