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抓取數據

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM