11.SCCB接口时序的实现

SCCB接口时序的实现

SCCB接口时序与IIC协议基本一致,是其简化版本,且SCCB协议兼容IIC协议。

基本时序介绍

最常用的时序是3线控制数据传输的方式,基本时序图如下。

image-20201211175052360

具体的控制信号,则是先发送起始信号,再发送数据,最后发送停止信号。

其中,3相数据传输又是最常用的方式。

起始信号为scl有效时,sda拉低。

image-20201211175316135

停止信号为scl有效时,sda拉高。

image-20201211175500687

正确的有效数据是scl为高电平时,sda保持不变,从而正确地读取数据,正好在时钟的上升沿读取有效数据。

image-20201211175520512

3相数据发送,即先发送器件地址,再发送子地址,最后发送需要写入的数据。

时序分析

根据上面的时序图,主要分为两部分来介绍整个时序实现的过程。

控制标志位产生

主要产生4个标志位,用于控制下面主体时序的是生成。

image-20201211180153008

scl的上升沿scl_pos_flag、下降沿scl_neg_flag以及sda的上升沿sda_pos_flag和下降沿sda_neg_flag四个控制信号,在主体的时序实现上起到很重要的作用。

主体时序分析

有个上图实现的4个控制信号,就可以很方便输出起始信号、停止信号以及数据信号。如下图所示。

image-20201211180312180

起始信号是在w_start_flag==1的范围内实现的,停止信号是在w_stop_flag==1的范围内实现的。数据信号是在phase_flag==1的范围内实现的。

时序测试

编写完成后,将其放入modelsim中进行测试。

image-20201211181019983

波形如上图所示,起始和停止信号在上图中已标出。

然后,使用ila抓取时序,查看波形信号。

下图中是w_end_flag的信号。

image-20201211223304979

还有w_start_flag的控制信号。

加入正确的控制信号后,再次进行测试。

OV5640摄像头控制

按照相应的寄存器写入控制寄存器,就可以获得正确的数据输出了。

寄存器配置

首先是信号的连接,看看下面的连接图。

image-20201212105007957

PCLK、cmos_data[9] ~ cmos_data[2]以及VSYNC和HREF作为输入信号,RESETB、PWDN和XCLK作为输出信号,主要的控制信号还有SDA和SCL信号,非常重要的信号。

控制时序如下图所示。

image-20201212105529161

步骤则如下。

步骤 1:
ResetB 拉低,复位 OV5640。 PWDN 引脚拉高。
步骤 2:
DOVDD 和 AVDD 上电。这两路最好同时上电,如果不能同时上电,那么必须使 DOVDD
上电在先,AVDD 上电在后。
步骤 3:
等 AVDD 稳定 5 毫秒后,拉低 PWDN。
步骤 4:
PWDN 置低 1 毫秒后, 拉高 ResetB。
步骤 5:
20 毫秒后, 初始化 OV5640 的 SCCB 寄存器设置。寄存器设置可参考第四章的 OV5640 软
件应用指南。

关于SCCB的寄存器控制,查看具体的寄存器配置。

OV5640_camera_module_software_application_notes_1.3_Sonix.pdf文件中包含1080p的配置寄存器的控制指令,下面只要发送相应的寄存器即可。

当然,对于某些寄存器的数值,必须了解数值所代表的含义,才方便进行针对性的修改。

ov5640能够支持的分辨率有1080P,Pclk最大为192MHz。

image-20201212142957823

在ov5640的数据手册中,还存在如下表格。

image-20201215141725318

关于具体的寄存器配置,查看正点原子2_领航者ZYNQ之嵌入式开发指南_V1.2.1.pdf关于ov5640的教程。

主要的控制寄存器,我们需要了解。

  1. 软件复位及电源复位。

image-20201212145539636

  1. 输出引脚使能控制

    image-20201212145632247

  2. 输出格式控制

image-20201212145724319

默认设置的是0x30,即输出格式为YUV422,输出顺序为{b[4:0],g[5:3]},{g[2:0],r[4:0]},需要将YUV格式的数据转换为RGB格式的数据。由于对于YUV422格式不熟悉,这里修改为0x61,即输出格式为RGB565,输出顺序为{r[4:0],g[5:3]},{g[2:0],g[4:0]}。

重点来了,输出图像的参数设置。看下面的图像就一目了然,具体的配置都设置好了。

image-20201212154857182

提取有效数据

再看看具体的时序,基本所有的数据就能提取出来了。最终的控制时序如下图所示。

image-20201212155744548

根据时序图,编写相应的控制代码。

这个比imx222简单多了,直接输出相应的数据和控制信号。

其读写控制和普通的SCCB控制还是有些区别的,主要在于其寄存器地址为16bit,而不是常见的8位,故变成了4相位数据写入。如下图所示。

image-20201215095203872

常用的三相位phase数据控制,phase 1写入器件地址,phase 2写寄存器地址,phase3写入器件地址。 image-20201215095312757

ov5640的SCCB理论上的写入顺序是一致的,不过器件寄存器地址变化了16bit,故变成了4 phase数据写入,理论上还是3 phase数据写入,参考正点原子领航者 ZYNQ 之嵌入式开发指南.pdf

上图中的 ID ADDRESS 是由 7 位器件地址和 1 位读写控制位构成( 0: 写 1: 读), OV5640 的器件地
址为 7’h3c,所以在写传输协议中, ID Address( W) = 8’h78(器件地址左移 1 位,低位补 0)

故Verilog代码需要修改为4 phase数据写入。

关于ov5640输出的时钟和数据信号的同步时序,如下图所示。

image-20201215115434941

输出的时钟PCLK的时钟的上升沿刚好与输出的有效数据D同步,能够采集到有效的图像数据。

ILA调试

将输入输出信号提取出来放在ILA中测试,发现输入数据是正确的,输出信号没有正确的提取,增加相应的控制信号,查看控制信号是否正确。

image-20201215143148276

发现行计数的最大值,hcnt不涉及的时序不符合,如上图所示。

参考以下博客,应该是寄存器关于2592和1944的部分没有配置正确。参考如下的链接OV5640摄像头时序实测与datasheet对不上求指导,很有可能是寄存器没有配置成功。

重新配置寄存器,问题解决了嘛。

image-20201215212731617

如上图所示,获得了正确的数据。

注意事项

  1. 关于axi-lite的控制

    PS为主控端,控制axi-lite接口读写数据。

    一般来说,PS为Master接口,PL为Slave接口,如下图所示。

    image-20201211220528411

    Master数据写入Slave

    PS端的主控制器写入数据到PL端的SCCB控制器,则SCCB控制器的寄存器获取主控制器发送的数据,如下面的代码所示。

    always @( posedge S_AXI_ACLK )
    	begin
    	  if ( S_AXI_ARESETN == 1'b0 )
    	    begin
    	      slv_reg0 <= 0;
    	      slv_reg1 <= 0;
    	    end 
    	  else begin
    	    if (slv_reg_wren)
    	      begin
    	        case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
    	          2'h0:
    	            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
    	              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
    	                // Slave register 0
    	                slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
    	              end  
    	          2'h1:
    	            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
    	              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
    	                // Slave register 1
    	                slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
    	              end  
    	          default : begin
    	                      slv_reg0 <= slv_reg0;
    	                      slv_reg1 <= slv_reg1;
    
    	                    end
    	        endcase
    	      end
    	  end
    	end
    

    具体来说,Master端写入数据是在W_DATA中传输,Slave端接口来自Master端的数据,数据都是在W_DATA中传输,接收的数据保存在相应的寄存器slv_reg0和slv_reg1,位于Slave的PL端想要使用这个数据的话,输出就行了。

    相应的控制条件应该这么写。

    	assign write_data = slv_reg0;
    	assign write_flag = slv_reg1;
    

    Master读取Slave数据

    对于Master端读取slave数据,则是在RD_DATA中传输,即Master读取Slave端的数据,Slave将要发送给Master端的数据存入寄存器slv_reg0和slv_reg1,再把寄存器中的数据存入reg_data中,最后reg_data_out中的数据放入共同的数据线RD_DATA,具体可见如下的代码。

    	assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
    	always @(*)
    	begin
    	      // Address decoding for reading registers
    	      case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
    	        2'h0   : reg_data_out <= slv_reg0;
    	        2'h1   : reg_data_out <= slv_reg1;
    	        default : reg_data_out <= 0;
    	      endcase
    	end
    
    	// Output register or memory read data
    	always @( posedge S_AXI_ACLK )
    	begin
    	  if ( S_AXI_ARESETN == 1'b0 )
    	    begin
    	      axi_rdata  <= 0;
    	    end 
    	  else
    	    begin    
    	      if (slv_reg_rden)
    	        begin
    	          axi_rdata <= reg_data_out;     // register read data
    	        end   
    	    end
    	end    
    

    相应的控制条件可以直接赋值给reg_data_out,就可以获得正确的结果。

    	assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
    	always @(*)
    	begin
    	      // Address decoding for reading registers
    	      case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
    	        2'h0   : reg_data_out <= slv_reg0;
    	        2'h1   : reg_data_out <= slv_reg1;
    	        2'h2   : reg_data_out <= write_end;//slv_reg2;
    	        2'h3   : reg_data_out <= slv_reg3;
    	        default : reg_data_out <= 0;
    	      endcase
    	end
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值