协议——SCCB与IIC的区别
SCCB(Serial Camera Control Bus,串行摄像头控制总线)是由OV(OmniVision的简称)公司定义和发展的三线式串行总线,该总线控制着摄像头大部分的功能,包括图像数据格式、分辨率以及图像处理参数等。结构框图如下所示:
OV公司为了减少传感器引脚的封装,现在SCCB总线大多采用两线式接口总线。OV7725使用的是两线式接口总线,该接口总线包括SIO_C串行时钟输入线和SIO_D串行双向数据线,分别相当于IIC协议的SCL信号线和SDA信号线。SIO_C的最小时间为10us,即最大频率为100K。一般来说,100K-400K之间都可以。
由此可见,SCCB就是改编版的IIC,完全可以按照IIC来理解,下面仔细讲解SCCB的时序以及和IIC的不同之处。
一、SCCB起始和结束(与IIC完全一致)
二、SCCB写(与IIC完全一致)
ID Address(W)里面就已经包括进了IIC中的“读写控制位”,所以没有额外写出。
即:start + phase_1 + phase_2 + phase_3 + stop
“X”的意思是“don't care”,该位是由从机发出应答信号来响应主机表示当前ID Address、Sub-address和Write Data是否传输完成,但是从机有可能不发出应答信号,因此主机(此处指FPGA)可不用判断此处是否有应答,直接默认当前传输完成即可。“X”即IIC中的ACK应答位。
三、SCCB读
数据手册中的SCCB读只写了上图的Phase3和Phase4,实际上它是和Phase1和Phase2联系在一起的。SCCB不支持连续读,Phase4的主机应答位必须为NA(no ack),即为1,所以SCCB读其实就专指单次读,和IIC单次读几乎一样。
区别就一点:在IIC读传输协议中,写完寄存器地址后会有restart即重复开始的操作;而SCCB读传输协议中没有重复开始的概念,在写完寄存器地址后,需发起总线停止信号。
即:start_1 + phase_1 + phase_2 + stop_1 + start_2 + phase_3 + phase_4 + stop_2
四、SCCB和IIC的区别
1.SCCB的应答位称为X,表示“don't care”,而IIC应答位称为ACK。
2.SCCB只能单次读,而IIC除了单次读还支持连续读。
3.SCCB读操作中间有stop,而IIC读操作中间可以有stop也可以不需要stop,具体表现如下
- SCCB读:start_1 + phase_1 + phase_2 + stop_1 + start_2 + phase_3 + phase_4 + stop_2
- IIC读:start_1 + phase_1 + phase_2 + + start_2 + phase_3 + phase_4 + stop_2
除去上面三点,SCCB和IIC再无区别,因此如果只需要配置寄存器(只用到写),可以直接拿IIC的时序来当做SCCB用,如果需要读,读操作中间必须有一个stop。
五、SCCB控制器Verilog代码
- //**************************************************************************
- // *** 名称 : sccb.v
- // *** 作者 : xianyu_FPGA
- // *** 博客 : https://www.cnblogs.com/xianyufpga/
- // *** 日期 : 2019-08-10
- // *** 描述 : SCCB控制器,只支持写
- //**************************************************************************
- module sccb
- //========================< 参数 >==========================================
- #(
- parameter DEVICE_ID = 'b01010000 , //器件ID
- parameter CLK = 'd50_000_000 , //本模块的时钟频率
- parameter SCL = 'd250_000 //输出的SCL时钟频率
- )
- //========================< 端口 >==========================================
- (
- input clk , //时钟
- input rst_n , //复位,低电平有效
- //SCCB control --------------------------------------
- input sccb_en , //SCCB触发信号
- input addr16_en , //16位地址使能
- input addr8_en , //8位地址使能
- //SCCB input ----------------------------------------
- input [:] sccb_addr , //SCCB器件内地址
- input [ :] sccb_data , //SCCB要写的数据
- //SCCB output ---------------------------------------
- output reg sccb_done , //SCCB一次操作完成
- output reg sccb_scl , //SCCB的SCL时钟信号
- inout sccb_sda , //SCCB的SDA数据信号
- //dri_clk -------------------------------------------
- output reg sccb_dri_clk //驱动SCCB操作的驱动时钟,1Mhz
- );
- //========================< 状态机参数 >====================================
- localparam IDLE = 'b00_0001 ; //空闲状态
- localparam DEVICE = 'b00_0010 ; //写器件地址
- localparam ADDR_16 = 'b00_0100 ; //写字地址高8位
- localparam ADDR_8 = 'b00_1000 ; //写字地址低8位
- localparam DATA = 'b01_0000 ; //写数据
- localparam STOP = 'b10_0000 ; //结束
- //========================< 信号 >==========================================
- reg sda_dir ; //SCCB数据(SDA)方向控制
- reg sda_out ; //SDA输出信号
- reg state_done ; //状态结束
- reg [ :] cnt ; //计数
- reg [ :] state_c ; //状态机当前状态
- reg [ :] state_n ; //状态机下一状态
- reg [:] sccb_addr_t ; //地址寄存
- reg [ :] sccb_data_t ; //数据寄存
- reg [ :] clk_cnt ; //分频时钟计数
- wire [ :] clk_divide ; //模块驱动时钟的分频系数
- //==========================================================================
- //== sda控制
- //==========================================================================
- assign sccb_sda = sda_dir ? sda_out : 'bz; //SDA数据输出或高阻
- //==========================================================================
- //== 生成SCL的4倍时钟来驱动后面SCCB的操作,生成1Mhz的sccb_dri_clk
- //==========================================================================
- assign clk_divide = (CLK/SCL) >> ; // >>3即除以8
- always @(posedge clk or negedge rst_n) begin
- if(!rst_n) begin
- sccb_dri_clk <= 'b1;
- clk_cnt <= 'd0;
- end
- else if(clk_cnt == clk_divide - 'd1) begin
- clk_cnt <= 'd0;
- sccb_dri_clk <= ~sccb_dri_clk;
- end
- else
- clk_cnt <= clk_cnt + 'b1;
- end
- //==========================================================================
- //== 状态机
- //==========================================================================
- always @(posedge sccb_dri_clk or negedge rst_n) begin
- if(!rst_n)
- state_c <= IDLE;
- else
- state_c <= state_n;
- end
- always @(*) begin
- case(state_c)
- IDLE: begin //空闲状态
- if(sccb_en)
- state_n = DEVICE;
- else
- state_n = IDLE;
- end
- DEVICE: begin //写器件ID
- if(state_done) begin
- if(addr16_en)
- state_n = ADDR_16;
- else if(addr8_en)
- state_n = ADDR_8 ;
- end
- else
- state_n = DEVICE;
- end
- ADDR_16: begin //写地址高8位
- if(state_done)
- state_n = ADDR_8;
- else
- state_n = ADDR_16;
- end
- ADDR_8: begin //写地址低8位
- if(state_done)
- state_n = DATA;
- else
- state_n = ADDR_8;
- end
- DATA: begin //写数据
- if(state_done)
- state_n = STOP;
- else
- state_n = DATA;
- end
- STOP: begin //结束
- if(state_done)
- state_n = IDLE;
- else
- state_n = STOP ;
- end
- default:state_n= IDLE;
- endcase
- end
- //==========================================================================
- //== 设计各路信号
- //==========================================================================
- always @(posedge sccb_dri_clk or negedge rst_n) begin
- if(!rst_n) begin
- sccb_scl <= 'b1;
- sda_out <= 'b1;
- sda_dir <= 'b1;
- sccb_done <= 'b0;
- cnt <= 'b0;
- state_done <= 'b0;
- sccb_addr_t <= 'b0;
- sccb_data_t <= 'b0;
- end
- else begin
- state_done <= 'b0 ;
- cnt <= cnt + 'b1 ;
- case(state_c)
- //--------------------------------------------------- 空闲状态
- IDLE: begin
- sccb_scl <= 'b1;
- sda_out <= 'b1;
- sda_dir <= 'b1;
- sccb_done <= 'b0;
- cnt <= 'b0;
- if(sccb_en) begin
- sccb_addr_t <= sccb_addr;
- sccb_data_t <= sccb_data;
- end
- end
- //--------------------------------------------------- 写器件ID
- DEVICE: begin
- case(cnt)
- 'd1 : sda_out <= 1'b0;
- 'd3 : sccb_scl <= 1'b0;
- 'd4 : sda_out <= DEVICE_ID[7];
- 'd5 : sccb_scl <= 1'b1;
- 'd7 : sccb_scl <= 1'b0;
- 'd8 : sda_out <= DEVICE_ID[6];
- 'd9 : sccb_scl <= 1'b1;
- 'd11: sccb_scl <= 1'b0;
- 'd12: sda_out <= DEVICE_ID[5];
- 'd13: sccb_scl <= 1'b1;
- 'd15: sccb_scl <= 1'b0;
- 'd16: sda_out <= DEVICE_ID[4];
- 'd17: sccb_scl <= 1'b1;
- 'd19: sccb_scl <= 1'b0;
- 'd20: sda_out <= DEVICE_ID[3];
- 'd21: sccb_scl <= 1'b1;
- 'd23: sccb_scl <= 1'b0;
- 'd24: sda_out <= DEVICE_ID[2];
- 'd25: sccb_scl <= 1'b1;
- 'd27: sccb_scl <= 1'b0;
- 'd28: sda_out <= DEVICE_ID[1];
- 'd29: sccb_scl <= 1'b1;
- 'd31: sccb_scl <= 1'b0;
- 'd32: sda_out <= DEVICE_ID[0];
- 'd33: sccb_scl <= 1'b1;
- 'd35: sccb_scl <= 1'b0;
- 'd36: begin
- sda_dir <= 'b0; //从机应答
- sda_out <= 'b1;
- end
- 'd37: sccb_scl <= 1'b1;
- 'd38: state_done <= 1'b1; //状态结束
- 'd39: begin
- sccb_scl <= 'b0;
- cnt <= 'b0;
- end
- default : ;
- endcase
- end
- //--------------------------------------------------- 写字地址高8位
- ADDR_16: begin
- case(cnt)
- 'd0 : begin
- sda_dir <= 'b1 ;
- sda_out <= sccb_addr_t[];
- end
- 'd1 : sccb_scl <= 1'b1;
- 'd3 : sccb_scl <= 1'b0;
- 'd4 : sda_out <= sccb_addr_t[14];
- 'd5 : sccb_scl <= 1'b1;
- 'd7 : sccb_scl <= 1'b0;
- 'd8 : sda_out <= sccb_addr_t[13];
- 'd9 : sccb_scl <= 1'b1;
- 'd11: sccb_scl <= 1'b0;
- 'd12: sda_out <= sccb_addr_t[12];
- 'd13: sccb_scl <= 1'b1;
- 'd15: sccb_scl <= 1'b0;
- 'd16: sda_out <= sccb_addr_t[11];
- 'd17: sccb_scl <= 1'b1;
- 'd19: sccb_scl <= 1'b0;
- 'd20: sda_out <= sccb_addr_t[10];
- 'd21: sccb_scl <= 1'b1;
- 'd23: sccb_scl <= 1'b0;
- 'd24: sda_out <= sccb_addr_t[9];
- 'd25: sccb_scl <= 1'b1;
- 'd27: sccb_scl <= 1'b0;
- 'd28: sda_out <= sccb_addr_t[8];
- 'd29: sccb_scl <= 1'b1;
- 'd31: sccb_scl <= 1'b0;
- 'd32: begin
- sda_dir <= 'b0; //从机应答
- sda_out <= 'b1;
- end
- 'd33: sccb_scl <= 1'b1;
- 'd34: state_done <= 1'b1; //状态结束
- 'd35: begin
- sccb_scl <= 'b0;
- cnt <= 'b0;
- end
- default : ;
- endcase
- end
- //--------------------------------------------------- 写字地址低8位
- ADDR_8: begin
- case(cnt)
- 'd0: begin
- sda_dir <= 'b1 ;
- sda_out <= sccb_addr_t[];
- end
- 'd1 : sccb_scl <= 1'b1;
- 'd3 : sccb_scl <= 1'b0;
- 'd4 : sda_out <= sccb_addr_t[6];
- 'd5 : sccb_scl <= 1'b1;
- 'd7 : sccb_scl <= 1'b0;
- 'd8 : sda_out <= sccb_addr_t[5];
- 'd9 : sccb_scl <= 1'b1;
- 'd11: sccb_scl <= 1'b0;
- 'd12: sda_out <= sccb_addr_t[4];
- 'd13: sccb_scl <= 1'b1;
- 'd15: sccb_scl <= 1'b0;
- 'd16: sda_out <= sccb_addr_t[3];
- 'd17: sccb_scl <= 1'b1;
- 'd19: sccb_scl <= 1'b0;
- 'd20: sda_out <= sccb_addr_t[2];
- 'd21: sccb_scl <= 1'b1;
- 'd23: sccb_scl <= 1'b0;
- 'd24: sda_out <= sccb_addr_t[1];
- 'd25: sccb_scl <= 1'b1;
- 'd27: sccb_scl <= 1'b0;
- 'd28: sda_out <= sccb_addr_t[0];
- 'd29: sccb_scl <= 1'b1;
- 'd31: sccb_scl <= 1'b0;
- 'd32: begin
- sda_dir <= 'b0; //从机应答
- sda_out <= 'b1;
- end
- 'd33: sccb_scl <= 1'b1;
- 'd34: state_done <= 1'b1; //状态结束
- 'd35: begin
- sccb_scl <= 'b0;
- cnt <= 'b0;
- end
- default : ;
- endcase
- end
- //--------------------------------------------------- 写数据
- DATA: begin
- case(cnt)
- 'd0: begin
- sda_out <= sccb_data_t[];
- sda_dir <= 'b1;
- end
- 'd1 : sccb_scl <= 1'b1;
- 'd3 : sccb_scl <= 1'b0;
- 'd4 : sda_out <= sccb_data_t[6];
- 'd5 : sccb_scl <= 1'b1;
- 'd7 : sccb_scl <= 1'b0;
- 'd8 : sda_out <= sccb_data_t[5];
- 'd9 : sccb_scl <= 1'b1;
- 'd11: sccb_scl <= 1'b0;
- 'd12: sda_out <= sccb_data_t[4];
- 'd13: sccb_scl <= 1'b1;
- 'd15: sccb_scl <= 1'b0;
- 'd16: sda_out <= sccb_data_t[3];
- 'd17: sccb_scl <= 1'b1;
- 'd19: sccb_scl <= 1'b0;
- 'd20: sda_out <= sccb_data_t[2];
- 'd21: sccb_scl <= 1'b1;
- 'd23: sccb_scl <= 1'b0;
- 'd24: sda_out <= sccb_data_t[1];
- 'd25: sccb_scl <= 1'b1;
- 'd27: sccb_scl <= 1'b0;
- 'd28: sda_out <= sccb_data_t[0];
- 'd29: sccb_scl <= 1'b1;
- 'd31: sccb_scl <= 1'b0;
- 'd32: begin
- sda_dir <= 'b0; //从机应答
- sda_out <= 'b1;
- end
- 'd33: sccb_scl <= 1'b1;
- 'd34: state_done <= 1'b1; //状态结束
- 'd35: begin
- sccb_scl <= 'b0;
- cnt <= 'b0;
- end
- default : ;
- endcase
- end
- //--------------------------------------------------- 结束
- STOP: begin
- case(cnt)
- 'd0: begin
- sda_dir <= 'b1;
- sda_out <= 'b0;
- end
- 'd1 : sccb_scl <= 1'b1;
- 'd3 : sda_out <= 1'b1;
- 'd15: state_done <= 1'b1; //状态结束
- 'd16: begin
- cnt <= 'b0;
- sccb_done <= 'b1; //sccb配置完成
- end
- default : ;
- endcase
- end
- endcase
- end
- end
- endmodule
参考资料:
[1]OmniVision Serial Camera Control Bus (SCCB) Functional Specification
[2]正点原子FPGA教程
[3]开源骚客.SDRAM那些事儿
协议——SCCB与IIC的区别的更多相关文章
- http、TCP/IP协议与socket之间的区别
http.TCP/IP协议与socket之间的区别 网络由下往上分为: www.2cto.com 物理层-- 数据链路层-- 网络层-- ...
- http、TCP/IP协议与socket之间的区别(转载)
http.TCP/IP协议与socket之间的区别 https://www.cnblogs.com/iOS-mt/p/4264675.html http.TCP/IP协议与socket之间的区别 ...
- 转 WebService两种发布协议--SOAP和REST的区别
转发文章 https://blog.csdn.net/zl834205311/article/details/62231545?ABstrategy=codes_snippets_optimize_v ...
- Python进阶----网络通信基础 ,OSI七层协议() ,UDP和TCP的区别 , TCP/IP协议(三次握手,四次挥手)
Python进阶----网络通信基础 ,OSI七层协议() ,UDP和TCP的区别 , TCP/IP协议(三次握手,四次挥手) 一丶CS/BS 架构 C/S: 客户端/服务器 定义: ...
- HTTP协议 结构,get post 区别(阿里面试)
如果需要想了解相关的TCP的协议结构,底层架构,以及每次面试必问的三次握手,四次挥手可以 参考:TCP协议详解7层和4层解析(美团面试,阿里面试) 尤其是三次握手,四次挥手 具体发送的报文和状态都要掌 ...
- WebService发布协议--SOAP和REST的区别
HTTP是标准超文本传输协议.使用对参数进行编码并将参数作为键值对传递,还使用关联的请求语义.每个协议都包含一系列HTTP请求标头及其他一些信息,定义客户端向服务器请求哪些内容,服务器用一系列HTTP ...
- Git使用总结 Asp.net生命周期与Http协议 托管代码与非托管代码的区别 通过IEnumerable接口遍历数据 依赖注入与控制反转 C#多线程——优先级 AutoFac容器初步 C#特性详解 C#特性详解 WPF 可触摸移动的ScrollViewer控件 .NET(C#)能开发出什么样的APP?盘点那些通过Smobiler开发的移动应用
一,原理 首先,我们要明白Git是什么,它是一个管理工具或软件,用来管理什么的呢?当然是在软件开发过程中管理软件或者文件的不同版本的工具,一些作家也可以用这个管理自己创作的文本文件,由Linus开发的 ...
- HTTP协议中GET和POST区别
GET一般用于获取和查询资源信息:POST一般用于更新信息,表示可能修改服务器上资源的请求 GET请求一般是幂等的 GET请求数据会附加在url之后,POST请求数据放到request-body中 G ...
- HTTP协议GET和POST的区别
from http://blog.csdn.net/whuslei/article/details/6667095 权威点的说明请参考:http://www.cs.tut.fi/~jkorpela/f ...
随机推荐
- jmxtrans docker-compose 运行
以下是一个简单的demo,使用jmxtrans 进行jmx 指标的处理,项目使用docker-compose 运行 同时写入数据到graphite 环境准备 docker-compose文件 ve ...
- 50、Spark Streaming实时wordcount程序开发
一.java版本 package cn.spark.study.streaming; import java.util.Arrays; import org.apache.spark.SparkCon ...
- Flume(一) —— 启动与基本使用
基础架构 Flume is a distributed, reliable(可靠地), and available service for efficiently(高效地) collecting, a ...
- 【大数据作业十一】分布式并行计算MapReduce
作业要求:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3319 1.用自己的话阐明Hadoop平台上HDFS和MapReduce的功 ...
- ls列出排除的文件
今天有个需求,将从日志文件夹中列出它排除旧备份日志的文件. ls -lhrt --ignore="*.gz" --ignore="*.zip"
- git - 3.分支
分支介绍 每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支.截止到目前,只有一条时间线, 在Git里,这个分支叫主分支,即master分支. HEAD严格来说不是指向提交,而是指向mas ...
- redis的相关原理
一.AOF 二.RDB 三.哨兵
- matlab学习笔记10_7数值计算类型和常用计算公式
一起来学matlab-matlab学习笔记11 数值数据类型以及特殊函数 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张德丰等著 ...
- 必备Linux命令
文章来源:https://macrozheng.github.io/mall-learning/#/reference/linux 开发者必备Linux命令 开发者必备Linux常用命令,掌握这些命令 ...
- SpringBoot 为什么能够自动的注入一些常用的Bean ?详细分析SpringBoot 自动配置的实现
转载至:https://blog.csdn.net/qq_29941401/article/details/79605388 有一个问题一直让我好奇,为什么在SpringBoot中有的bean 我们都 ...