Menu Close

图像采集与传输系统(摄像头控制模块)

摄像头控制模块(reg_config_camera_ov5640_phy.v)用于控制ov5640的相关操作, 绝大多数操作都会在初始化过程中完成, 少量的操作会在实际工程中使用。当ov5640上电复位模块准备好后(提供initial_en信号),  摄像头控制模块就可以正常配置ov5640的相关参数了。(具体参数内容, 可以参照ov5640 的技术手册)

参考目录:图像采集与传输系统的设计

ov5640模块控制框图:

%title插图%num图1

其中power_on_delay_ov5640_phy.v 模块是提供ov5640上电和reset的逻辑,同时输出initial_en 给reg_config_camera_ov5640_phy.v 模块,

1)摄像头控制模块得到initial_en后,通过i2c总线,开始对ov5640硬件的相关寄存器进行配置。

2)当所有寄存器配置完成后,转入到控制模式,接收flash_switch的信号,点亮或者熄灭ov5640硬件上的闪光灯。

3)同时, 摄像头模块也是可以接收,发送 uart数据的, 这时uart作为ov5640寄存器的调试接口, 可以将uart 数据转换为 i2c的数据发送给ov5640,也可以通过i2c 控制, 将ov5640的寄存器读出, 发送到uart上。

%title插图%num

reg_config_camera_ov5640_phy.v (摄像头控制模块)可以分为以下几个部分:

i2c_master_top.v : i2c IP ,用于控制 i2c 总线上的数据读写。

按键(return键)控制逻辑: 用于接收按键信息, 点亮、熄灭闪光灯。

i2c控制状态机: 1)初始化ov5640的相关寄存器, 2)读取按键信息,发送i2c 命令到ov5640硬件, 点亮,熄灭闪光灯。

camera 初始化数据:一组静态数据,在系统启动时, 会被初始化状态机所调用, 将这些数据写入到ov5640 芯片中去。

串口调试逻辑:在状态机空闲期间, 可以使用uart 接口 ,接收uart 数据写入到ov5640寄存器中, 也可以根据uart 命令,读取ov5640 芯片寄存器中的数据, 并发送这些数据到uart上。

具体程序解析:

 

闪光灯控制逻辑:

assign reg_conf_done = reg_conf_done_reg ;

/* 
闪光灯开关信号st_Strobe的产生,按键每按一次(改变st_mux),
sign_Strobe的值在2'b01或者2'b10间进行一次赋值。(sign_Strobe为2'b01,
打开闪光灯。sign_Strobe为2'b10,则关闭闪光灯)
*/
reg [1:0] sign_Strobe = 2'b00;
reg st_mux = 0;

always @ ( posedge clk_50m)
if (!initial_en) 
begin
    sign_Strobe <= 2'b00;
    st_mux <= 0;
end
else 
begin 
    if ( flash_switch ) 
    begin 
        sign_Strobe <= st_mux ? 2'b10 : 2'b01; 
        st_mux <= st_mux + 1;
    end 
    else sign_Strobe <= 2'b00;
end

 

接收flash_switch 过来的按键信息, 每当按键按下一次, st_mux 就翻转一次,同时使用sign_strobe  记录当前的按键状态; sign_strobe = 2’b01 , 打开闪光灯, sign_strobe = 2’b10 , 关闭闪光灯。

 

状态机控制逻辑:

// 首先配置基本的253个寄存器,OV5640摄像头可以正常工作,采集图像。
// 寄存器253,254的作用分别是打开闪光灯,关闭闪光灯。

reg [1:0] i2c_st = 0; 
always@(posedge clk_50m ) 
if(!initial_en) // OV5640摄像头上电未完成时,配置寄存器的电路模块处于复位状态
begin
    i2c_st <= 0;
    reg_wr_i2c <= 0;
    reg_index <= 0;
    reg_conf_done_reg <= 0;
end
else 
begin
    // 整个寄存器的配置过程分为2部分,基本寄存器的配置(0~252),
    // 闪光灯寄存器的配置两部分。基本寄存器的配置在reg_conf_done_reg为低电平的状态下实现 
    if(reg_conf_done_reg == 1'b0) 
    begin 
        if( reg_index <= 252 ) 
        begin
            // 调用IIC总线配置(0~252)寄存器的值,配置完成后,将reg_conf_done_reg值拉高
            case(i2c_st)
            0: 
            begin
                i2c_data <= {ov5640_devide_id, 1'b0, reg_data};
                reg_wr_i2c <= 1;
                i2c_st <= 1;
            end
            1: 
            begin
                if(wr_done_i2c) 
                begin 
                    reg_wr_i2c <= 0;
                    i2c_st <= 2;
                end
                else ;
            end
            2: 
            begin
                reg_index <= reg_index + 1'b1;
                i2c_st <= 0;
            end
            endcase
        end
        else 
            reg_conf_done_reg <= 1'b1;
    end
    else 
    begin 
        // 在reg_conf_done_reg为高电平阶段,等待闪光灯开关命令(即向摄像头模块OV564的03b00寄存器写入不同的寄存器值 )。
        //(通过闪光灯开关按键调整sign_Strobe的值,进行执行对闪光灯控制寄存器写入不同的值的过程)
        case(i2c_st)
        0: 
        begin
            if( sign_Strobe == 2'b01 ) 
            begin 
                i2c_st <= 1;
                reg_index <= 253; 
            end
            else 
            begin 
                if (sign_Strobe == 2'b10) 
                begin // 
                    i2c_st <= 1 ;
                    reg_index <= 254 ; 
                end
                else ; 
            end 
        end 
        1: 
        begin
            i2c_data <= {ov5640_devide_id, 1'b0, reg_data }; //IIC Device address is 0x3c 
            reg_wr_i2c <= 1;
            i2c_st <= 2;
        end
        2: 
        begin
            if(wr_done_i2c)
            begin //IIC发送结束 
                reg_wr_i2c <= 0;
                i2c_st <= 3;
            end
            else ;
        end
        3: 
        begin
            i2c_st <= 0;
            reg_index <= 253; 
        end
        endcase
    end
end

在initial_en == 0 时, 所有状态, 变量 清零。 当initial_en == 1 时: (允许状态机对0v5640 进行初始化操作)

如果没有完成初始化操作(reg_conf_done_reg == 0) , 初始化ov5640 相关的寄存器, 知道所需要的寄存器全部初始化完毕。将reg_confi_done_reg = 1;

如果完成了初始化操作, 等待按键是否被按下,检测不同的按键值,然后将按键所代表的含义(点亮 flash led, 熄灭 flash led)发送给ov5640.

 

camera 初始化数据:

camera 初始化数据,用于初始化camera芯片,完成相关的配置工作,包括camera 芯片的时钟设置,分辨率的设置,图像采样设置,输出模式设置,图像位置设置,图像颜色调整等, 很多操作。 这里我们选择的时 640×480@30Hz ,RGB565, DVP 模式,将图像数据输出给fpga。 很多具体的操作,需要仔细阅读ov5640的相关寄存器手册。

 

uart 转i2c 控制逻辑:

/*
本模块的功能是在线调试OV5640寄存器 。工程中经常使用串口来在线读写寄存器,通过写入的值和读出来的值进行比对一致性判断
(1:验证IIC总线的读写的正确性,2.可以快速进行相关寄存器的配置,)命令格式 参考本工程PDF文档附件
*/
// uart read and write 5640 configuration register 
// 串口接收计算机(波特率115200)下发的寄存器配置命令
//************* 串口在线配置OV5640寄存器

reg [2:0] uart_st = 0;
always @ (posedge clk_50m)
if(reg_conf_done_reg == 0)
begin
    uart_wr_i2c <= 0 ;
    uart_rd_i2c <= 0 ;
    uart_st <= 0 ;
    uart_sel <= 0 ;
end
else 
begin 
    case ( uart_st )
    0:
    begin 
        txd_start <= 0;
        uart_wr_i2c <= 0;
        uart_rd_i2c <= 0;
        if(rxd_done & (rxd_data == 01) ) // 串口发送第1byte数据为01,则之后的配置命令对OV5640执行
            uart_st <= 1 ; 
        else 
            uart_st <= 0 ;
    end 
    1:
    begin
        uart_wr_i2c <= 0 ;
        uart_rd_i2c <= 0 ; 
        uart_sel <= 1 ; // IIC的读写请求命令,地址等相关信息切换到串口通道 
        if(rxd_done)
        begin 
            cmd_dir <= rxd_data ; // 接收读写命令
            uart_st <= 2 ;
        end
        else ;
    end
    2:
    begin
        if(rxd_done)
        begin
            i2c_data_r[23:16] <= rxd_data ; //接收读写寄存器地址高8bit数据
            uart_st <= 3 ;
        end
        else ;
    end
    3:
    begin
        if( rxd_done )
        begin
            i2c_data_r[15:08] <= rxd_data ; //接收读写寄存器地址低8bit数据
            if(cmd_dir[0]) 
                uart_st <= 6 ; //依据接收的读或者写命令调用IIC总线进行读操作或者写操作
            else 
                uart_st <= 4 ;
        end
        else ;
    end
    4: // write cmd
    begin
        if(rxd_done)
        begin
            i2c_data_r[07:00] <= rxd_data; //待写入5640摄像头寄存器的8bit数据
            uart_wr_i2c <= 1;
            uart_st <= 5;
        end
        else ;
    end
    5:
    begin
        if( wr_done_i2c ) 
        begin
            uart_wr_i2c <= 0;
            uart_sel <= 0;
            uart_st <= 0; 
        end
        else ; 
    end
    6: //read cmd
    begin
        uart_rd_i2c <= 1;
        uart_st <= 7;
    end
    7:
    begin
        if( rd_done_i2c )
        begin
            uart_rd_i2c <= 0;
            txd_data <= i2c_read_data ; // 读回来的数据给到串口的发送端口
            txd_start <= 1 ;
            uart_sel <= 0 ;
            uart_st <= 0 ;
        end
    end
    endcase
end

 

uart 转i2c 控制逻辑:

状态0: 等待uart 是否有数据被接收到, 同时查看一下接收到的第一个数据是否为01, 如果数据为01,表示uart 准备调试camera; 如果为02,表示uart 准备调试adv7511.

状态1: 等待uart 接收第二个数据,这个数据为I2C的地址,并且从这个数据的最低位还能判断出对I2C的读写操作。同时uart_sel 切换I2C master IP 到uart上。

状态2:接收数据为寄存器的高8位数据

状态3:接收数据为寄存器的低8位数据,同时判断uart的操作: I2C 读, I2C写,根据不同的操作,跳转到不同的状态机。

状态4:写操作,将下一个uart 接收到的数据写入I2C (给寄存器赋值)

状态5:写操作完成, 同时将uart_sel 切换到数据初始化状态机上。

状态6:对I2C master IP 进行读操作

状态7:将I2C 读取到的数据,发送到uart 上。

 

示例:

%title插图%num

uart 的调试方法在“图像采集uart 在线调试使用文档说明”中有详细描述。 使用方法:使用计算机uart 工具,举例sscom。uart 115200波特率 , hex 显示, hex 发送。

举例:

01 78 4741 07

01 78 4741 00

01 78 503D 80

01 78 503D 00

 

uart 调试 ov5640 芯片 格式为:

调试命令: id(1byte) + i2c 地址(1byte) + 寄存器(2bytes)

调试命令: id(1byte) + i2c 地址(1byte) + 寄存器(2bytes)+ 寄存器值(1byte)

id : 8bit , 01 = ov5640; 02 = adv7511. 用来指示当前的调试命令和哪个模块通讯(ov5640,adv7511)

i2c地址: 8bit, 在读命令中 这个地址的最低位是‘1’,在写命令中这个地址的最低为是‘0’。

寄存器:ov5640 的寄存器是16bit的, 对于adv7511来说, 寄存器是由8bit,所以,在读写adv7511时:都是00xx,将高位地址 设置位‘00’。

寄存器值:8bit, 写命令才有。 写入寄存器的值。

Posted in FPGA, FPGA, Verilog, Verilog, 教材与教案, 文章
0 0 投票数
Article Rating
订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论

相关链接