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抓取数据

     

  • 相关阅读:
    CSS之旅——第二站 如何更深入的理解各种选择器
    CSS之旅——第一站 为什么要用CSS
    记录一些在用wcf的过程中走过的泥巴路 【第一篇】
    asp.net mvc 之旅—— 第二站 窥探Controller下的各种Result
    asp.net mvc 之旅—— 第一站 从简单的razor入手
    Sql Server之旅——终点站 nolock引发的三级事件的一些思考
    Sql Server之旅——第十四站 深入的探讨锁机制
    Sql Server之旅——第十三站 对锁的初步认识
    Sql Server之旅——第十二站 sqltext的参数化处理
    Sql Server之旅——第十一站 简单说说sqlserver的执行计划
  • 原文地址:https://www.cnblogs.com/bixiaopengblog/p/7527942.html
Copyright © 2011-2022 走看看