zoukankan      html  css  js  c++  java
  • OV7670读操作

    这篇文章主要介绍一下verilog读ov7670的出厂序列号

    读时序共分为五个部分

    • 首先发送start,然后发送OV7670的器件地址,ov6070的ID是0x42,0x42+一位响应位
    • 发送ov7670的寄存器地址,这里可以读取它的厂商识别号 ,比如1c  发送八位寄存器+接受一位响应位
    • ov7670的SCCB时序不同与iic时序,在发送完第一个部分需要比iic时序多发送一个stop,那就是stop+start
    • 再次发送ov7670的器件地址,这次需要指定读写,第八位是读写控制位,0是写,1是读,即0x43+响应位
    • 最后就是接受数据,需要注意的是最后不是响应位,而是NA,发送高电平即可,最后跟一个结束stop

    ov7670管脚

    • pwdn是睡眠模式,0工作,1睡眠
    • rst_n  复位   低电平复位 高电平工作
    • XCLK系统时钟输入 官方手册推荐使用24M
    • SCl IIC时钟引脚  我用的是100K
    • SDA IIC数据输入   

    简单的列一下程序

    • 100K时钟产生

    IIC时钟对时钟要求不严格,所以采用进位的方法进行分频,所产生的时钟频率略小于100K,

    div_en是使能信号,如果采用使能时钟可能会出现问题。

    • 时序采用状态机的方法一步步执行,相对比较直观

    • 响应标志位,因为数据位是双向口,需要在响应时间设置位输入

    • 状态机
    //--------------------------------
    //Funtion : sda_reg
    
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
        begin
            iic_clk1 <= 1'd1;
            sda_reg <= 1'd1;
            riic_data <= 1'd0;
        end
        else if(dir == 1'b1)    //read
            case(time_cnt)
                //idle
                6'd0 : begin
                            iic_clk1 <= 1'd1;
                            sda_reg <= 1'd1;  
                       end
                //start
                6'd1 :begin
                            iic_clk1 <= 1'd1;
                            sda_reg <= 1'd0;
                      end
                6'd2 :begin
                            iic_clk1 <= 1'd0;
                            sda_reg <= 1'd0;
                      end
                            
                //ID_addr
                6'd3 :        sda_reg <= wdata_reg[23];
                6'd4 :        sda_reg <= wdata_reg[22];
                6'd5 :        sda_reg <= wdata_reg[21];
                6'd6 :        sda_reg <= wdata_reg[20];
                6'd7 :        sda_reg <= wdata_reg[19];
                6'd8 :        sda_reg <= wdata_reg[18];
                6'd9 :        sda_reg <= wdata_reg[17];
                6'd10:        sda_reg <= wdata_reg[16];                
                //ack
                6'd11:        iic_clk1<= 1'd0;
                6'd12:                       ;
                6'd13:        iic_clk1<= 1'd0;
                //sub_addr
                6'd14:        sda_reg <= wdata_reg[15];
                6'd15:        sda_reg <= wdata_reg[14];
                6'd16:        sda_reg <= wdata_reg[13];
                6'd17:        sda_reg <= wdata_reg[12];
                6'd18:        sda_reg <= wdata_reg[11];
                6'd19:        sda_reg <= wdata_reg[10];
                6'd20:        sda_reg <= wdata_reg[9];
                6'd21:        sda_reg <= wdata_reg[8];    
                //ack
                6'd22:        iic_clk1<= 1'd0;
                6'd23:                       ;
                6'd24:        iic_clk1<= 1'd0;
                //stop
                6'd25:begin
                            iic_clk1 <= 1'd1;
                            sda_reg  <= 1'd0;
                      end
                6'd26:begin
                            iic_clk1 <= 1'd1;
                            sda_reg  <= 1'd1;
                      end
                //start
                6'd27:begin
                            iic_clk1 <= 1'd1;
                            sda_reg  <= 1'd1;
                      end
                6'd28:begin
                            iic_clk1 <= 1'd1;
                            sda_reg  <= 1'd0;
                      end
                //ID_addr
                6'd29:        sda_reg <= wdata_reg[7];
                6'd30:        sda_reg <= wdata_reg[6];
                6'd31:        sda_reg <= wdata_reg[5];
                6'd32:        sda_reg <= wdata_reg[4];
                6'd33:        sda_reg <= wdata_reg[3];
                6'd34:        sda_reg <= wdata_reg[2];
                6'd35:        sda_reg <= wdata_reg[1];
                6'd36:        sda_reg <= wdata_reg[0];    
                //ack
                6'd37:        iic_clk1<= 1'd0;
                6'd38:                       ;
                6'd39:        iic_clk1<= 1'd0;
                //read_data
                6'd40:        riic_data[7] <= iic_sda;
                6'd41:        riic_data[6] <= iic_sda;
                6'd42:        riic_data[5] <= iic_sda;
                6'd43:        riic_data[4] <= iic_sda;
                6'd44:        riic_data[3] <= iic_sda;
                6'd45:        riic_data[2] <= iic_sda;
                6'd46:        riic_data[1] <= iic_sda;
                6'd47:        riic_data[0] <= iic_sda;
                //nack
                6'd48:        sda_reg <= 1'd1;
                //stop
                6'd49:begin
                            iic_clk1 <= 1'd1;
                            sda_reg  <= 1'd0;
                      end
                6'd50:begin
                            iic_clk1 <= 1'd1;
                            sda_reg  <= 1'd1;
                      end
                default :
                        begin
                            iic_clk1 <= 1'd1;
                            sda_reg  <= 1'd1;
                        end
            endcase     
    end
    • iic_clk和iic_sda

      sda是双向端口,在输入的1时候设置为高阻态

     dir是读写方向控制段,这里只是读所以置一

    • sigtab抓取数据

     

  • 相关阅读:
    [one day one question] safari缓存太厉害
    对工厂方法模式的一些思考(2)
    对工厂方法模式的一些思考(java语法表示)
    [选译]MySQL5.7以上Zip版官方安装文档
    clojure 使用阿里云仓库
    对jbox2d引擎的一些回顾与思考(swing实现demo)
    定位
    空白空间及溢出的处理
    BFC
    高度自适应
  • 原文地址:https://www.cnblogs.com/bixiaopengblog/p/7527942.html
Copyright © 2011-2022 走看看