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完全一致)

  起始:SIO_C为高时,SIO_D由高拉低。

  停止:SIO_C为高时,SIO_D由低拉高

二、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_2IIC读:start_1 + phase_1 + phase_2 +        + start_2 + phase_3 + phase_4 + stop_2

  除去上面三点,SCCB和IIC再无区别,因此如果只需要配置寄存器(只用到写),可以直接拿IIC的时序来当做SCCB用,如果需要读,读操作中间必须有一个stop。

 五、SCCB控制器Verilog代码

  1 //**************************************************************************2 // *** 名称 : sccb.v3 // *** 作者 : xianyu_FPGA4 // *** 博客 : https://www.cnblogs.com/xianyufpga/5 // *** 日期 : 2019-08-106 // *** 描述 : SCCB控制器,只支持写7 //**************************************************************************8 9 module sccb10 //========================< 参数 >==========================================11 #(12 parameter DEVICE_ID         = 8'b01010000           , //器件ID13 parameter CLK               = 26'd50_000_000        , //本模块的时钟频率14 parameter SCL               = 18'd250_000             //输出的SCL时钟频率15 )16 //========================< 端口 >==========================================17 (18 input                       clk                     , //时钟19 input                       rst_n                   , //复位,低电平有效20 //SCCB control -------------------------------------- 21 input                       sccb_en                 , //SCCB触发信号22 input                       addr16_en               , //16位地址使能23 input                       addr8_en                , //8位地址使能24 //SCCB input ---------------------------------------- 25 input        [15:0]         sccb_addr               , //SCCB器件内地址26 input        [ 7:0]         sccb_data               , //SCCB要写的数据27 //SCCB output --------------------------------------- 28 output  reg                 sccb_done               , //SCCB一次操作完成29 output  reg                 sccb_scl                , //SCCB的SCL时钟信号30 inout                       sccb_sda                , //SCCB的SDA数据信号31 //dri_clk ------------------------------------------- 32 output  reg                 sccb_dri_clk              //驱动SCCB操作的驱动时钟,1Mhz33 );34 //========================< 状态机参数 >====================================35 localparam  IDLE            = 6'b00_0001            ; //空闲状态36 localparam  DEVICE          = 6'b00_0010            ; //写器件地址37 localparam  ADDR_16         = 6'b00_0100            ; //写字地址高8位38 localparam  ADDR_8          = 6'b00_1000            ; //写字地址低8位39 localparam  DATA            = 6'b01_0000            ; //写数据40 localparam  STOP            = 6'b10_0000            ; //结束41 //========================< 信号 >==========================================42 reg                         sda_dir                 ; //SCCB数据(SDA)方向控制43 reg                         sda_out                 ; //SDA输出信号44 reg                         state_done              ; //状态结束45 reg    [ 6:0]               cnt                     ; //计数46 reg    [ 7:0]               state_c                 ; //状态机当前状态47 reg    [ 7:0]               state_n                 ; //状态机下一状态48 reg    [15:0]               sccb_addr_t             ; //地址寄存49 reg    [ 7:0]               sccb_data_t             ; //数据寄存50 reg    [ 9:0]               clk_cnt                 ; //分频时钟计数51 wire   [ 8:0]               clk_divide              ; //模块驱动时钟的分频系数52 53 //==========================================================================54 //==    sda控制55 //==========================================================================56 assign  sccb_sda = sda_dir ?  sda_out : 1'bz;         //SDA数据输出或高阻57 58 //==========================================================================59 //==     生成SCL的4倍时钟来驱动后面SCCB的操作,生成1Mhz的sccb_dri_clk60 //==========================================================================61 assign  clk_divide = (CLK/SCL) >> 3;                  // >>3即除以862 63 always @(posedge clk or negedge rst_n) begin64     if(!rst_n) begin65         sccb_dri_clk <=  1'b1;66         clk_cnt <= 10'd0;67     end68     else if(clk_cnt == clk_divide - 1'd1) begin69         clk_cnt <= 10'd0;70         sccb_dri_clk <= ~sccb_dri_clk;71     end72     else73         clk_cnt <= clk_cnt + 1'b1;74 end75 76 //==========================================================================77 //==    状态机78 //==========================================================================79 always @(posedge sccb_dri_clk or negedge rst_n) begin80     if(!rst_n)81         state_c <= IDLE;82     else83         state_c <= state_n;84 end85 86 always @(*) begin87     case(state_c)88         IDLE: begin                             //空闲状态89            if(sccb_en)90                state_n = DEVICE;91            else92                state_n = IDLE;93         end94         DEVICE: begin                           //写器件ID95             if(state_done) begin96                 if(addr16_en)97                    state_n = ADDR_16;98                 else if(addr8_en)99                    state_n = ADDR_8 ;
100             end
101             else
102                 state_n = DEVICE;
103         end
104         ADDR_16: begin                          //写地址高8位
105             if(state_done)
106                 state_n = ADDR_8;
107             else
108                 state_n = ADDR_16;
109         end
110         ADDR_8: begin                           //写地址低8位
111             if(state_done)
112                 state_n = DATA;
113             else
114                 state_n = ADDR_8;
115         end
116         DATA: begin                             //写数据
117             if(state_done)
118                 state_n = STOP;
119             else
120                 state_n = DATA;
121         end
122         STOP: begin                             //结束
123             if(state_done)
124                 state_n = IDLE;
125             else
126                 state_n = STOP ;
127         end
128         default:state_n= IDLE;
129     endcase
130 end
131
132 //==========================================================================
133 //==    设计各路信号
134 //==========================================================================
135 always @(posedge sccb_dri_clk or negedge rst_n) begin
136     if(!rst_n) begin
137         sccb_scl    <= 1'b1;
138         sda_out     <= 1'b1;
139         sda_dir     <= 1'b1;
140         sccb_done   <= 1'b0;
141         cnt         <= 1'b0;
142         state_done  <= 1'b0;
143         sccb_addr_t <= 1'b0;
144         sccb_data_t <= 1'b0;
145     end
146     else begin
147         state_done  <= 1'b0 ;
148         cnt         <= cnt + 1'b1 ;
149         case(state_c)
150             //--------------------------------------------------- 空闲状态
151             IDLE: begin
152                     sccb_scl  <= 1'b1;
153                     sda_out   <= 1'b1;
154                     sda_dir   <= 1'b1;
155                     sccb_done <= 1'b0;
156                     cnt       <= 7'b0;
157                     if(sccb_en) begin
158                         sccb_addr_t <= sccb_addr;
159                         sccb_data_t <= sccb_data;
160                     end
161             end
162             //--------------------------------------------------- 写器件ID
163             DEVICE: begin
164                 case(cnt)
165                     7'd1 : sda_out  <= 1'b0;
166                     7'd3 : sccb_scl <= 1'b0;
167                     7'd4 : sda_out  <= DEVICE_ID[7];
168                     7'd5 : sccb_scl <= 1'b1;
169                     7'd7 : sccb_scl <= 1'b0;
170                     7'd8 : sda_out  <= DEVICE_ID[6];
171                     7'd9 : sccb_scl <= 1'b1;
172                     7'd11: sccb_scl <= 1'b0;
173                     7'd12: sda_out  <= DEVICE_ID[5];
174                     7'd13: sccb_scl <= 1'b1;
175                     7'd15: sccb_scl <= 1'b0;
176                     7'd16: sda_out  <= DEVICE_ID[4];
177                     7'd17: sccb_scl <= 1'b1;
178                     7'd19: sccb_scl <= 1'b0;
179                     7'd20: sda_out  <= DEVICE_ID[3];
180                     7'd21: sccb_scl <= 1'b1;
181                     7'd23: sccb_scl <= 1'b0;
182                     7'd24: sda_out  <= DEVICE_ID[2];
183                     7'd25: sccb_scl <= 1'b1;
184                     7'd27: sccb_scl <= 1'b0;
185                     7'd28: sda_out  <= DEVICE_ID[1];
186                     7'd29: sccb_scl <= 1'b1;
187                     7'd31: sccb_scl <= 1'b0;
188                     7'd32: sda_out  <= DEVICE_ID[0];
189                     7'd33: sccb_scl <= 1'b1;
190                     7'd35: sccb_scl <= 1'b0;
191                     7'd36: begin
192                             sda_dir <= 1'b0;    //从机应答
193                             sda_out <= 1'b1;
194                     end
195                     7'd37: sccb_scl <= 1'b1;
196                     7'd38: state_done <= 1'b1;  //状态结束
197                     7'd39: begin
198                             sccb_scl <= 1'b0;
199                             cnt <= 1'b0;
200                     end
201                     default :  ;
202                 endcase
203             end
204             //--------------------------------------------------- 写字地址高8位
205             ADDR_16: begin
206                 case(cnt)
207                     7'd0 : begin
208                             sda_dir <= 1'b1 ;
209                             sda_out <= sccb_addr_t[15];
210                     end
211                     7'd1 : sccb_scl <= 1'b1;
212                     7'd3 : sccb_scl <= 1'b0;
213                     7'd4 : sda_out  <= sccb_addr_t[14];
214                     7'd5 : sccb_scl <= 1'b1;
215                     7'd7 : sccb_scl <= 1'b0;
216                     7'd8 : sda_out  <= sccb_addr_t[13];
217                     7'd9 : sccb_scl <= 1'b1;
218                     7'd11: sccb_scl <= 1'b0;
219                     7'd12: sda_out  <= sccb_addr_t[12];
220                     7'd13: sccb_scl <= 1'b1;
221                     7'd15: sccb_scl <= 1'b0;
222                     7'd16: sda_out  <= sccb_addr_t[11];
223                     7'd17: sccb_scl <= 1'b1;
224                     7'd19: sccb_scl <= 1'b0;
225                     7'd20: sda_out  <= sccb_addr_t[10];
226                     7'd21: sccb_scl <= 1'b1;
227                     7'd23: sccb_scl <= 1'b0;
228                     7'd24: sda_out  <= sccb_addr_t[9];
229                     7'd25: sccb_scl <= 1'b1;
230                     7'd27: sccb_scl <= 1'b0;
231                     7'd28: sda_out  <= sccb_addr_t[8];
232                     7'd29: sccb_scl <= 1'b1;
233                     7'd31: sccb_scl <= 1'b0;
234                     7'd32: begin
235                            sda_dir  <= 1'b0;    //从机应答
236                            sda_out  <= 1'b1;
237                     end
238                     7'd33: sccb_scl <= 1'b1;
239                     7'd34: state_done <= 1'b1;  //状态结束
240                     7'd35: begin
241                            sccb_scl <= 1'b0;
242                            cnt <= 1'b0;
243                     end
244                     default :  ;
245                 endcase
246             end
247             //--------------------------------------------------- 写字地址低8位
248             ADDR_8: begin
249                 case(cnt)
250                     7'd0: begin
251                             sda_dir <= 1'b1 ;
252                             sda_out <= sccb_addr_t[7];
253                     end
254                     7'd1 : sccb_scl <= 1'b1;
255                     7'd3 : sccb_scl <= 1'b0;
256                     7'd4 : sda_out  <= sccb_addr_t[6];
257                     7'd5 : sccb_scl <= 1'b1;
258                     7'd7 : sccb_scl <= 1'b0;
259                     7'd8 : sda_out  <= sccb_addr_t[5];
260                     7'd9 : sccb_scl <= 1'b1;
261                     7'd11: sccb_scl <= 1'b0;
262                     7'd12: sda_out  <= sccb_addr_t[4];
263                     7'd13: sccb_scl <= 1'b1;
264                     7'd15: sccb_scl <= 1'b0;
265                     7'd16: sda_out  <= sccb_addr_t[3];
266                     7'd17: sccb_scl <= 1'b1;
267                     7'd19: sccb_scl <= 1'b0;
268                     7'd20: sda_out  <= sccb_addr_t[2];
269                     7'd21: sccb_scl <= 1'b1;
270                     7'd23: sccb_scl <= 1'b0;
271                     7'd24: sda_out  <= sccb_addr_t[1];
272                     7'd25: sccb_scl <= 1'b1;
273                     7'd27: sccb_scl <= 1'b0;
274                     7'd28: sda_out  <= sccb_addr_t[0];
275                     7'd29: sccb_scl <= 1'b1;
276                     7'd31: sccb_scl <= 1'b0;
277                     7'd32: begin
278                            sda_dir  <= 1'b0;    //从机应答
279                            sda_out  <= 1'b1;
280                     end
281                     7'd33: sccb_scl <= 1'b1;
282                     7'd34: state_done <= 1'b1;  //状态结束
283                     7'd35: begin
284                            sccb_scl <= 1'b0;
285                            cnt <= 1'b0;
286                     end
287                     default :  ;
288                 endcase
289             end
290             //--------------------------------------------------- 写数据
291             DATA: begin
292                 case(cnt)
293                     7'd0: begin
294                             sda_out <= sccb_data_t[7];
295                             sda_dir <= 1'b1;
296                     end
297                     7'd1 : sccb_scl <= 1'b1;
298                     7'd3 : sccb_scl <= 1'b0;
299                     7'd4 : sda_out  <= sccb_data_t[6];
300                     7'd5 : sccb_scl <= 1'b1;
301                     7'd7 : sccb_scl <= 1'b0;
302                     7'd8 : sda_out  <= sccb_data_t[5];
303                     7'd9 : sccb_scl <= 1'b1;
304                     7'd11: sccb_scl <= 1'b0;
305                     7'd12: sda_out  <= sccb_data_t[4];
306                     7'd13: sccb_scl <= 1'b1;
307                     7'd15: sccb_scl <= 1'b0;
308                     7'd16: sda_out  <= sccb_data_t[3];
309                     7'd17: sccb_scl <= 1'b1;
310                     7'd19: sccb_scl <= 1'b0;
311                     7'd20: sda_out  <= sccb_data_t[2];
312                     7'd21: sccb_scl <= 1'b1;
313                     7'd23: sccb_scl <= 1'b0;
314                     7'd24: sda_out  <= sccb_data_t[1];
315                     7'd25: sccb_scl <= 1'b1;
316                     7'd27: sccb_scl <= 1'b0;
317                     7'd28: sda_out  <= sccb_data_t[0];
318                     7'd29: sccb_scl <= 1'b1;
319                     7'd31: sccb_scl <= 1'b0;
320                     7'd32: begin
321                            sda_dir  <= 1'b0;    //从机应答
322                            sda_out  <= 1'b1;
323                     end
324                     7'd33: sccb_scl <= 1'b1;
325                     7'd34: state_done <= 1'b1;  //状态结束
326                     7'd35: begin
327                            sccb_scl  <= 1'b0;
328                            cnt  <= 1'b0;
329                     end
330                     default  :  ;
331                 endcase
332             end
333             //--------------------------------------------------- 结束
334             STOP: begin
335                 case(cnt)
336                     7'd0: begin
337                            sda_dir  <= 1'b1;
338                            sda_out  <= 1'b0;
339                     end
340                     7'd1 : sccb_scl <= 1'b1;
341                     7'd3 : sda_out  <= 1'b1;
342                     7'd15: state_done <= 1'b1;  //状态结束
343                     7'd16: begin
344                            cnt <= 1'b0;
345                            sccb_done <= 1'b1;   //sccb配置完成
346                     end
347                     default  : ;
348                 endcase
349             end
350         endcase
351     end
352 end
353
354
355
356 endmodule

参考资料:

[1]OmniVision Serial Camera Control Bus (SCCB) Functional Specification

[2]正点原子FPGA教程

[3]开源骚客.SDRAM那些事儿

--------------------------------------------------------------------------------------

作者:咸鱼FPGA

出处:https://www.cnblogs.com/xianyufpga/

本文版权归作者所有,如需转载请保留此段声明。

协议——SCCB与IIC的区别相关推荐

  1. 协议--SCCB与IIC的区别

    学习摘自FPGA开源工作室 SCCB(Serial Camera Control Bus,串行摄像头控制总线)是由OV(OmniVision的简称)公司定义和发展的三线式串行总线,该总线控制着摄像头大 ...

  2. SCCB与IIC的异同及FPGA实现的注意事项

    本文主要参考了两种协议的规范文档和一个摄像头传感器(OV7725)的数据手册,文档链接如下: IIC规范:UM10204 SCCB规范:SCCBSpec_AN OV7725数据手册:OV7725 1. ...

  3. 模拟IIC与硬件IIC的区别!

    模拟IIC与硬件IIC的区别! 一:模拟IIC与硬件IIC定义? 模拟I2C一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形. 硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所 ...

  4. http、TCP/IP协议与socket之间的区别

    网络由下往上分为:  www.2cto.com   物理层--                       数据链路层-- 网络层--                       IP协议 传输层-- ...

  5. 光纤收发器和协议转换器之间有哪些区别?

    在通信网络领域,我们经常会用到光纤收发器和协议转换器,但对此不是很了解的朋友,往往可能会将二者搞混淆.那么,关于光纤收发器与协议转换器之间有什么区别呢?接下来就跟随杭州飞畅的小编一起来看看吧! 光纤收 ...

  6. 协议和服务器有什么区别,服务期协议是什么,劳动合同与服务期协议有什么区别?...

    一.服务期协议是什么? 服务期协议是用人单位与劳动者约定的劳动者为用人单位必须服务的期限.服务期协议不同与劳动合同,劳动合同是用人的单位与劳动者约定的劳动关系存续的存续期间的约定,劳动合同主要适用劳动 ...

  7. 面试篇-- Http、TCP/IP协议与Socket之间的区别

    网络由下往上分为: 物理层-- 数据链路层-- 网络层-- IP协议 传输层-- TCP协议 会话层-- 表示层和应用层-- HTTP协议 1.TCP/IP连接 手机能够使用联网功能是因为手机底层实现 ...

  8. Zigbee无线协议 和 WiFi通信协议的区别

    亿佰特物联网无线通信:Zigbee无线协议 和 WiFi通信协议的区别 物联网领域无线数据传输指的是无线数传模块将工业设备输出或者各种采集的数据进行远程传送,可以无线模拟量采集,也能无线开关量控制.无 ...

  9. Python进阶----网络通信基础 ,OSI七层协议() ,UDP和TCP的区别 , TCP/IP协议(三次握手,四次挥手)...

    Python进阶----网络通信基础 ,OSI七层协议() ,UDP和TCP的区别 , TCP/IP协议(三次握手,四次挥手) 一丶CS/BS 架构 C/S: 客户端/服务器 定义:       这里 ...

最新文章

  1. centos7上安装redis6-0-5
  2. 用C语言写的万年历---亲手写的。好累哦
  3. java aio聊天_JAVA aio简单使用
  4. win7 找不到 计算机策略组,win7打开组策略报错:找不到资源string.Advanced_EnableSSL3Fallback...
  5. 修改 Joomla! 1.5 的 HTML 输出而不动核心文件 (附api文档)
  6. Oracle数据库启动以及说明
  7. Bzoj5251: [2018多省省队联测]劈配
  8. android uri 电话号码,android 跳转通讯录 Android跳转到通讯录获取用户名称和手机号码的实现思路...
  9. 什么是AWT_Swing_Scroll面板,上!!!
  10. 遗传算法 python_Python实现入门级遗传算法
  11. 大学生适合学习的软件 网站推荐
  12. SpringBoot 无法捕获 maximum upload size exceeded
  13. STL全特化 偏特化 成员特化
  14. 监听audio是否加载完毕
  15. 人工智能小白日记 语音情感分析探索之2 CNN相关及实验
  16. STM32F429IGT6使用SDRAM(W9825G6KH-6)
  17. 太原理工大学计算机院招生网,相洁-太原理工大学信息与计算机学院
  18. java上下文控制,Esper事件处理引擎_8_EPL 语法_2_Context 上下文_2_条件控制
  19. java中当前时间查询_SQL 查询当前时间
  20. html写的迷宫游戏,网页开发游戏,js实现游戏

热门文章

  1. matlab word报告,MATLAB 实验报告
  2. 从项目管理角度谈OA流程优化
  3. 简单讲解ANSI Unicode、GBK、GB2312
  4. [转载]ios 开发 icon图标设置
  5. J2EE金融项目开发实战视频教程
  6. 临摹 x 科幻 x AI | MixTalk S01-09
  7. element-ui日期时间选择框picker-options如何禁用时间范围
  8. PostGre使用总结
  9. python制作的简单的猜数小游戏
  10. 一道很有意思的面试题目,快加入到这场头脑风暴游戏里吧~