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抓取数据
版权声明:本文为bixiaopengblog原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。