国产化驱动经济自主性与科技创新的未来之路
915
2022-10-30
FPGA-(OV摄像头SCCB协议)IIC驱动代码
SCCB(OmniVision serial camera control bus),即串行摄像机控制总线。OmniVision 公司已经定义和
采纳的SCCB总线是一种三线结构的串行总线,用于完成对绝大多数OmniVision 系列图像传芯片功能的控制。
在简化的引脚封装中,SCCB总线可以工作在改进的两线工作方式下。
两线SCCB接口有两条通迅连接线,即SIO_D(数据线)和 SIO_C(时钟线),下面是双总线功能原理图:
在双总线情况下,要求主控机有以下两种功能之一来支持SCCB通迅:
1、主控器件支持并能保持数据在三态模式;
2、如果不支持三态,
二、管脚功能
主控器件管脚描述
从控器件管脚描述
SCCB——E 信号
低电平有效,一个高到低的转换表明数据传输开始;一个低到高的转换表明数据传输结束;数据传输过程保持为低
电平;高电平表明总线处于空闲状态。在SCCB——E表明数据传输开始之前主机必须将数据线SIO——D置为1,这样可以避免
总线数据传输开始之前的总线不确定状态的出现。
SIO——C 信号
高电平有效,当处于空闲状态时必须被拉高;当启动传输后,SIO——C被拉低表明数据传输的开始,传输过程中高电平
表明一位数据正在传输,所以SIO——D的数据变化只能在SIO——C为低时发生,一位传输时间定义为tCYC,最小为10us。
三总线数据传输
SIO——D信号
可以被主机和从机驱动,当总线处于空闲时保持悬浮或三态;
在传输Don‘t-Car()e或NA位时,总线浮动和争用是允许的
SIO——C的一个高电平表明一位数据的传输,SIO——D只能在SIO——C的低电平期间发生变化,但在传输的开始和结束
也有例外,在SCCB——E断言并且SIO——C拉低之前,SIO——D可以被拉低,在SIO——C拉高之前和去断言之前,SIO——D
也可以被拉低。
数据传输的起始
SCCB——E由高到低的变化,表明数据传输的开始,在SCCB——E断言之前,主机必须把SIO——D拉高,这样可以避免
在数据传输之前传输一个不确定的总线状态;在SCCB——E去断言之后,主机必须把SIO——D拉高在一个定义的时间段
内,来再次避免一个不确定状态的总线状态传输。
在启动传输过程中有两个时间参数,TPRA和TPRC,TPRC被定义为SID——D预充电时间,这表明SIO——D必须先于
SCCB——E被拉高的时间,最小值为15ns,TPRA被是指在SIO——D拉低之前,SID——E必须被断言的时间,最小为1.25us。
数据传输的终止
TPSC是SCCB——E去断言后,SIO——D保持逻辑高电平的时间,最小为15ns,TPSA
是SIO——D去断言后,SCCB——E必须保持低电平的时间,最小为0ns。
上面贴的博客源:
因为这个是兼容iic的所以我直接写我再版整理的IIC的思路代码
使用task书写但是下板有问题跑仿真可以,不要模仿
等我研究出来再整理
module I2C_driver( clk, rst_n, I2C_wr_data, I2C_wr_req, SCL, SDA, ACK ); input clk; input rst_n; input [23:0]I2C_wr_data; input I2C_wr_req; output reg SCL; inout SDA; output ACK; reg[7:0] temp; parameter I2C_FREQ =250, //时钟频率 SEND_BIT =8; //发送数据位数 parameter Init =5'd0, START =5'd1, IP_ADDR =5'd2, ACK_0 =5'd3, SUB_ADDR =5'd4, ACK_1 =5'd5, WR_DATA =5'd6, ACK_2 =5'd7, STOP =5'd8, WAIT =5'd9; //------------------------------------------------- reg [7:0]cnt;//scl计数寄存器 reg [2:0]byte_cnt;//数据位寄存器 reg [4:0]state;//状态寄存器 reg sdar;//sda缓存 reg sdarlink; //sdar方向控制器 0-input 1-output assign SCL_HCapture =(cnt==(I2C_FREQ>>2)&&clk==1'b1); assign SCL_LCapture =((cnt==(I2C_FREQ>>2)*3)&&clk==1'b1); assign SDA =sdarlink?sdar:1'bz; assign ACK =(state==WAIT); /*---------iic时钟信号产生逻辑----------*/ always@(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin cnt<=1'b0; end else if(cnt==I2C_FREQ-1'b1)begin cnt<=1'b0; end else begin cnt<=cnt+1'b1; end end always @(posedge clk or negedge rst_n)begin if(rst_n == 1'b0)begin SCL <= 1'b0; end else if(cnt <= (I2C_FREQ>>1)-1'b1)begin SCL <= 1'b1; end else begin SCL <= 1'b0; end end /*---使能等待---*/ task Wait_Init; begin if(I2C_wr_req==1'b1)begin state<=state+1'b1; end else begin state<=state; end end endtask /*---起始---*/ task I2C_START; begin sdarlink<=1'b1; if(SCL_HCapture==1'b1)begin sdar<=1'b0; byte_cnt<=SEND_BIT-1'b1; state<=state+1'b1; end end endtask /*---停止---*/ task I2C_STOP; begin if(SCL_LCapture==1'b1)begin sdarlink<=1'b1; sdar<=1'b0; end else if(SCL_HCapture==1'b1)begin sdar<=1'b1; state<=state+1'b1; end else begin sdar<=sdar; end end endtask /*---应答---*/ task I2C_ANK; begin byte_cnt<=SEND_BIT-1'b1; sdar<=1'bz; state<=state+1'b1; end endtask /*--非应答--*/ task I2C_NPANK; begin byte_cnt<=SEND_BIT-1'b1; sdar<=1'b0; state<=state+1'b1; end endtask /*---发送数据or指令---*/ task I2C_Send_Byte; input [SEND_BIT-1'b1:0]Send_byte; begin if(SCL_LCapture==1'b1)begin sdar<=Send_byte[byte_cnt]; if(byte_cnt!=1'b0)begin byte_cnt<=byte_cnt-1'b1; end else begin state<=state+1'b1; end end end endtask always@(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin sdar<=1'b1; state<=Init; end else begin case(state) Init :Wait_Init(); START :I2C_START(); IP_ADDR :I2C_Send_Byte(I2C_wr_data[23:16]); ACK_0 :I2C_ANK(); SUB_ADDR:I2C_Send_Byte(I2C_wr_data[15:8]); ACK_1 :I2C_ANK(); WR_DATA :I2C_Send_Byte(I2C_wr_data[7:0]); ACK_2 :I2C_ANK(); STOP :I2C_STOP(); WAIT :state<=Init; default:state<=5'bxxxxx; endcase end endendmodule
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~