OV5640摄像头配置一些值得注意的关键点(三)

一、字节标志的注意点

    由于摄像头的输出是RGB56格式,所以需要将两帧的数据进行拼接,之后送到上位机进行显示。

 1 reg    byte_flag;
 2 
 3 always@(posedge cmos_pclk_i)
 4 begin
 5     if(!rst_n_reg[4])
 6         byte_flag <= 0;
 7     else if(cmos_href_r)
 8         byte_flag <= ~byte_flag;
 9     else
10         byte_flag <= 0;
11 end

上面always块是对拼接的两帧数据设置一个标志信号,在byte_flag==1时进行拼接,既然要进行拼接,就需要将数据进行同步寄存,故有

always@(posedge cmos_pclk_i)
begin
    if(!rst_n_reg[4])
        cmos_data_d0 <= 8'd0;
    else if(cmos_href_r)
        cmos_data_d0 <= cmos_data_r;    //MSB -> LSB
    else if(~cmos_href_r) 
        cmos_data_d0 <= 8'd0;
end

将当前的摄像头输出数据cmos_data_r寄存到cmos_data_d0,相当于延迟了一个时钟。

那么,在什么时候进行拼接,就是在byte_flag==1时,可是需要注意第一个always块的byte_falg赋值是在cmos_pclk_i的下一个时钟的上升沿完成,在第一个always块结束时byte_flag还是0,需要等待byte_falg==1,所以第三个always块

reg [15:0] rgb565;
always@(posedge cmos_pclk_i)
begin
    if(!rst_n_reg[4])
        rgb565 <= 16'd0;
    else if(cmos_href_r&byte_flag)
        rgb565 <= {cmos_data_d0,cmos_data_r};    //MSB -> LSB
    else if(~cmos_href_r) 
        rgb565 <= 8'd0;
end

上述always块等待byte_flag变为高电平。当byte_flag==1时候进行两帧数据拼接。

由于数据需要拼接,拼接完毕后的数据才是有效数据,那么必然需要一个标志作为输出有效信号,也就是表明此时数据有效的信号,所以存在以下代码块:

reg    byte_flag_r0;
always@(posedge cmos_pclk_i)
begin
    if(!rst_n_reg[4])
        byte_flag_r0 <= 0;
    else 
        byte_flag_r0 <= byte_flag;
end

assign    clk_ce =out_en? byte_flag_r0:1'b0;

为什么需要定义byte_flag_r0将byte_flag延时一个像素时钟呢?因为byte_flag_r0比byte_flga延时一个像素时钟,在这个延时的时钟过程中,完成数据的拼接,当完成数据拼接后,正好此时的数据有效且byte_flag_r0==1,故将byte_flag_r0作为输出有效标志。

将上面的第一个第二个always块写在一起更容易明白,可参考小梅哥例程中的配置方式,

    //capture and sync RGB565 cmos_din
    reg    [7:0]    cmos_din_r;
    reg    [15:0]    cmos_frame_data_r;
    reg            byte_flag;
    always@(posedge cmos_pclk or negedge rst_n)
    if(!rst_n) begin
        cmos_din_r <= 0;
        byte_flag <= 0;
        cmos_frame_data_r <= 0;
    end
    else if(cmos_href) begin
        byte_flag <= ~byte_flag;
        cmos_din_r <= cmos_din;
        if(byte_flag == 1'b1)
            cmos_frame_data_r <= {cmos_din_r, cmos_din};    //MSB -> LSB
        else
            cmos_frame_data_r <= cmos_frame_data_r;
    end
    else begin
        cmos_din_r <= 0;
        byte_flag <= 0;
        cmos_frame_data_r <= cmos_frame_data_r;
    end

(二)、此外,在代码案例中,存在前n个帧数据丢弃的情况,目前见过10帧、12帧、15帧,其作用个人理解为预留出5640摄像头的IIC配置初始化过程。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于SDRAM使用OV5620进行图像读取的Verilog代码框架图: ``` module ov5620_image_capture #( parameter WIDTH = 640, // 图像宽度 parameter HEIGHT = 480, // 图像高度 parameter ADDR_WIDTH = 19, // SDRAM 地址宽度 parameter DATA_WIDTH = 16 // SDRAM 数据宽度 ) ( input clk, // 时钟信号 input rst, // 复位信号 input [7:0] ov_data, // OV5620 数据 input ov_vsync, // OV5620 垂直同步信号 input ov_href, // OV5620 行同步信号 output reg [ADDR_WIDTH-1:0] sdram_addr, // SDRAM 地址 output reg [DATA_WIDTH-1:0] sdram_data, // SDRAM 数据 output reg sdram_wr_en // SDRAM 写使能信号 ); reg [8:0] cnt_h; // 行计数器 reg [8:0] cnt_w; // 列计数器 always@(posedge clk or posedge rst) begin if(rst) begin cnt_h <= 0; cnt_w <= 0; sdram_addr <= 0; sdram_wr_en <= 1'b0; end else begin if(ov_vsync == 1'b1 && ov_href == 1'b1) begin // 行同步信号和垂直同步信号同时为高电平时表示一帧图像开始 cnt_h <= 0; cnt_w <= 0; sdram_addr <= 0; sdram_wr_en <= 1'b0; end else if(ov_href == 1'b1) begin // 行同步信号为高电平时表示一行图像数据到来 cnt_h <= cnt_h + 1; cnt_w <= 0; end else begin // 普通像素数据 cnt_w <= cnt_w + 1; if(cnt_w < WIDTH && cnt_h < HEIGHT) begin sdram_data <= ov_data; sdram_addr <= (cnt_h * WIDTH + cnt_w) << 1; sdram_wr_en <= 1'b1; end else begin sdram_wr_en <= 1'b0; end end end end endmodule ``` 这个代码框架实现了OV5620图像采集和将采集到的图像数据存储到SDRAM中。你可以根据自己的需求进行修改和完善,比如可以修改图像的分辨率和存储方式等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值