SCCB(Serial Camera Control Bus,串行攝像頭控制總線)是由OV(OmniVision的簡稱)公司定義和發(fā)展的三線式串行總線,該總線控制著攝像頭大部分的功能,包括圖像數(shù)據(jù)格式、分辨率以及圖像處理參數(shù)等。結(jié)構(gòu)框圖如下所示:
OV公司為了減少傳感器引腳的封裝,現(xiàn)在SCCB總線大多采用兩線式接口總線。OV7725使用的是兩線式接口總線,該接口總線包括SIO_C串行時鐘輸入線和SIO_D串行雙向數(shù)據(jù)線,分別相當(dāng)于IIC協(xié)議的SCL信號線和SDA信號線。SIO_C的最小時間為10us,即最大頻率為100K。一般來說,100K-400K之間都可以。
由此可見,SCCB就是改編版的IIC,完全可以按照IIC來理解,下面仔細(xì)講解SCCB的時序以及和IIC的不同之處。
一、SCCB起始和結(jié)束(與IIC完全一致)
二、SCCB寫(與IIC完全一致)
ID Address(W)里面就已經(jīng)包括進(jìn)了IIC中的“讀寫控制位”,所以沒有額外寫出。
即:start + phase_1 + phase_2 + phase_3 + stop
“X”的意思是“don't care”,該位是由從機(jī)發(fā)出應(yīng)答信號來響應(yīng)主機(jī)表示當(dāng)前ID Address、Sub-address和Write Data是否傳輸完成,但是從機(jī)有可能不發(fā)出應(yīng)答信號,因此主機(jī)(此處指FPGA)可不用判斷此處是否有應(yīng)答,直接默認(rèn)當(dāng)前傳輸完成即可?!癤”即IIC中的ACK應(yīng)答位。
三、SCCB讀
數(shù)據(jù)手冊中的SCCB讀只寫了上圖的Phase3和Phase4,實(shí)際上它是和Phase1和Phase2聯(lián)系在一起的。SCCB不支持連續(xù)讀,Phase4的主機(jī)應(yīng)答位必須為NA(no ack),即為1,所以SCCB讀其實(shí)就專指單次讀,和IIC單次讀幾乎一樣。
區(qū)別就一點(diǎn):在IIC讀傳輸協(xié)議中,寫完寄存器地址后會有restart即重復(fù)開始的操作;而SCCB讀傳輸協(xié)議中沒有重復(fù)開始的概念,在寫完寄存器地址后,需發(fā)起總線停止信號。
即:start_1 + phase_1 + phase_2 + stop_1 + start_2 + phase_3 + phase_4 + stop_2
四、SCCB和IIC的區(qū)別
1.SCCB的應(yīng)答位稱為X,表示“don't care”,而IIC應(yīng)答位稱為ACK。
2.SCCB只能單次讀,而IIC除了單次讀還支持連續(xù)讀。
3.SCCB讀操作中間有stop,而IIC讀操作中間可以有stop也可以不需要stop,具體表現(xiàn)如下
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
除去上面三點(diǎn),SCCB和IIC再無區(qū)別,因此如果只需要配置寄存器(只用到寫),可以直接拿IIC的時序來當(dāng)做SCCB用,如果需要讀,讀操作中間必須有一個stop。
五、SCCB控制器Verilog代碼
1 //************************************************************************** 2 // *** 名稱 : sccb.v 3 // *** 作者 : xianyu_FPGA 4 // *** 博客 : https://www.cnblogs.com/xianyufpga/ 5 // *** 日期 : 2019-08-10 6 // *** 描述 : SCCB控制器,只支持寫 7 //************************************************************************** 8 9 module sccb 10 //========================< 參數(shù) >========================================== 11 #( 12 parameter DEVICE_ID = 8'b01010000 , //器件ID 13 parameter CLK = 26'd50_000_000 , //本模塊的時鐘頻率 14 parameter SCL = 18'd250_000 //輸出的SCL時鐘頻率 15 ) 16 //========================< 端口 >========================================== 17 ( 18 input clk , //時鐘 19 input rst_n , //復(fù)位,低電平有效 20 //SCCB control -------------------------------------- 21 input sccb_en , //SCCB觸發(fā)信號 22 input addr16_en , //16位地址使能 23 input addr8_en , //8位地址使能 24 //SCCB input ---------------------------------------- 25 input [15:0] sccb_addr , //SCCB器件內(nèi)陸址 26 input [ 7:0] sccb_data , //SCCB要寫的數(shù)據(jù) 27 //SCCB output --------------------------------------- 28 output reg sccb_done , //SCCB一次操作完成 29 output reg sccb_scl , //SCCB的SCL時鐘信號 30 inout sccb_sda , //SCCB的SDA數(shù)據(jù)信號 31 //dri_clk ------------------------------------------- 32 output reg sccb_dri_clk //驅(qū)動SCCB操作的驅(qū)動時鐘,1Mhz 33 ); 34 //========================< 狀態(tài)機(jī)參數(shù) >==================================== 35 localparam IDLE = 6'b00_0001 ; //空閑狀態(tài) 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 ; //寫數(shù)據(jù) 40 localparam STOP = 6'b10_0000 ; //結(jié)束 41 //========================< 信號 >========================================== 42 reg sda_dir ; //SCCB數(shù)據(jù)(SDA)方向控制 43 reg sda_out ; //SDA輸出信號 44 reg state_done ; //狀態(tài)結(jié)束 45 reg [ 6:0] cnt ; //計數(shù) 46 reg [ 7:0] state_c ; //狀態(tài)機(jī)當(dāng)前狀態(tài) 47 reg [ 7:0] state_n ; //狀態(tài)機(jī)下一狀態(tài) 48 reg [15:0] sccb_addr_t ; //地址寄存 49 reg [ 7:0] sccb_data_t ; //數(shù)據(jù)寄存 50 reg [ 9:0] clk_cnt ; //分頻時鐘計數(shù) 51 wire [ 8:0] clk_divide ; //模塊驅(qū)動時鐘的分頻系數(shù) 52 53 //========================================================================== 54 //== sda控制 55 //========================================================================== 56 assign sccb_sda = sda_dir ? sda_out : 1'bz; //SDA數(shù)據(jù)輸出或高阻 57 58 //========================================================================== 59 //== 生成SCL的4倍時鐘來驅(qū)動后面SCCB的操作,生成1Mhz的sccb_dri_clk 60 //========================================================================== 61 assign clk_divide = (CLK/SCL) >> 3; // >>3即除以8 62 63 always @(posedge clk or negedge rst_n) begin 64 if(!rst_n) begin 65 sccb_dri_clk <= 1'b1; 66 clk_cnt <= 10'd0; 67 end 68 else if(clk_cnt == clk_divide - 1'd1) begin 69 clk_cnt <= 10'd0; 70 sccb_dri_clk <= ~sccb_dri_clk; 71 end 72 else 73 clk_cnt <= clk_cnt + 1'b1; 74 end 75 76 //========================================================================== 77 //== 狀態(tài)機(jī) 78 //========================================================================== 79 always @(posedge sccb_dri_clk or negedge rst_n) begin 80 if(!rst_n) 81 state_c <= IDLE; 82 else 83 state_c <= state_n; 84 end 85 86 always @(*) begin 87 case(state_c) 88 IDLE: begin //空閑狀態(tài) 89 if(sccb_en) 90 state_n = DEVICE; 91 else 92 state_n = IDLE; 93 end 94 DEVICE: begin //寫器件ID 95 if(state_done) begin 96 if(addr16_en) 97 state_n = ADDR_16; 98 else if(addr8_en) 99 state_n = ADDR_8 ;100 end101 else102 state_n = DEVICE;103 end104 ADDR_16: begin //寫地址高8位105 if(state_done)106 state_n = ADDR_8;107 else108 state_n = ADDR_16;109 end110 ADDR_8: begin //寫地址低8位111 if(state_done)112 state_n = DATA;113 else114 state_n = ADDR_8;115 end116 DATA: begin //寫數(shù)據(jù)117 if(state_done)118 state_n = STOP;119 else120 state_n = DATA;121 end122 STOP: begin //結(jié)束123 if(state_done)124 state_n = IDLE;125 else126 state_n = STOP ;127 end128 default:state_n= IDLE;129 endcase130 end131 132 //==========================================================================133 //== 設(shè)計各路信號134 //==========================================================================135 always @(posedge sccb_dri_clk or negedge rst_n) begin136 if(!rst_n) begin137 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 end146 else begin147 state_done <= 1'b0 ;148 cnt <= cnt + 1'b1 ;149 case(state_c)150 //--------------------------------------------------- 空閑狀態(tài)151 IDLE: begin152 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) begin158 sccb_addr_t <= sccb_addr;159 sccb_data_t <= sccb_data;160 end161 end162 //--------------------------------------------------- 寫器件ID163 DEVICE: begin164 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: begin192 sda_dir <= 1'b0; //從機(jī)應(yīng)答193 sda_out <= 1'b1;194 end195 7'd37: sccb_scl <= 1'b1;196 7'd38: state_done <= 1'b1; //狀態(tài)結(jié)束197 7'd39: begin198 sccb_scl <= 1'b0;199 cnt <= 1'b0;200 end201 default : ;202 endcase203 end204 //--------------------------------------------------- 寫字地址高8位205 ADDR_16: begin206 case(cnt)207 7'd0 : begin208 sda_dir <= 1'b1 ;209 sda_out <= sccb_addr_t[15];210 end211 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: begin235 sda_dir <= 1'b0; //從機(jī)應(yīng)答236 sda_out <= 1'b1;237 end238 7'd33: sccb_scl <= 1'b1;239 7'd34: state_done <= 1'b1; //狀態(tài)結(jié)束240 7'd35: begin241 sccb_scl <= 1'b0;242 cnt <= 1'b0;243 end244 default : ;245 endcase246 end247 //--------------------------------------------------- 寫字地址低8位248 ADDR_8: begin249 case(cnt)250 7'd0: begin251 sda_dir <= 1'b1 ;252 sda_out <= sccb_addr_t[7];253 end254 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: begin278 sda_dir <= 1'b0; //從機(jī)應(yīng)答279 sda_out <= 1'b1;280 end281 7'd33: sccb_scl <= 1'b1;282 7'd34: state_done <= 1'b1; //狀態(tài)結(jié)束283 7'd35: begin284 sccb_scl <= 1'b0;285 cnt <= 1'b0;286 end287 default : ;288 endcase289 end290 //--------------------------------------------------- 寫數(shù)據(jù)291 DATA: begin292 case(cnt)293 7'd0: begin294 sda_out <= sccb_data_t[7];295 sda_dir <= 1'b1;296 end297 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: begin321 sda_dir <= 1'b0; //從機(jī)應(yīng)答322 sda_out <= 1'b1;323 end324 7'd33: sccb_scl <= 1'b1;325 7'd34: state_done <= 1'b1; //狀態(tài)結(jié)束326 7'd35: begin327 sccb_scl <= 1'b0;328 cnt <= 1'b0;329 end330 default : ;331 endcase332 end333 //--------------------------------------------------- 結(jié)束334 STOP: begin335 case(cnt)336 7'd0: begin337 sda_dir <= 1'b1;338 sda_out <= 1'b0;339 end340 7'd1 : sccb_scl <= 1'b1;341 7'd3 : sda_out <= 1'b1;342 7'd15: state_done <= 1'b1; //狀態(tài)結(jié)束343 7'd16: begin344 cnt <= 1'b0;345 sccb_done <= 1'b1; //sccb配置完成346 end347 default : ;348 endcase349 end350 endcase351 end352 end353 354 355 356 endmodule
參考資料:
[1]OmniVision Serial Camera Control Bus (SCCB) Functional Specification
[2]正點(diǎn)原子FPGA教程
[3]開源騷客.SDRAM那些事兒
聯(lián)系客服