■SCCB紹介
SCCB (Serial Camera Control Bus) は、OmniVision社のシリアル カメラ バス プロトコルです。OV7670 などの OV で始まるカメラ モジュールは、SCCB プロトコルを使用します。I2C プロトコルと類似しているため、SIO_C、SIO_DをSCL、SDAと呼びます。
本文は2線式SCCBプロトコルの内容とプログラム実装を中心に解説します。
■回路図
2線式SCCBに対して、SIO_CとSIO_Dだけを接続すればよいです。
■プロトコルの内容とプログラム実装
2 線式 SCCB バス
プロトコル解析
<1>送信開始フラグ: 送信 (データの読み取りまたは書き込み) ごとに、下図に従って SIO_C と SIO_D に指定されたHIGH-LOWレベルを出力する必要があります。対応するレベルを受け取ると、Slaveは転送開始が判ります。次のように操作します。SIO_CがHIGHのままでSIO_DをHIGHからLOWに変換して、SIO_CをLOWに戻ります。
void SCCB_Start(void) {
SCCB_SDA = 1;
SCCB_SCL = 1;
delay_us(50);
SCCB_SDA = 0;
delay_us(50);
SCCB_SCL = 0;
}
<2>送信完了フラグ:Slaveに送信完了を通知します。次のように操作します。SIO_CがHIGHのままでSIO_DをLOWからHIGHに変換します。
void SCCB_Stop(void) {
SCCB_SDA = 0;
delay_us(50);
SCCB_SCL = 1;
delay_us(50);
SCCB_SDA = 1;
delay_us(50);
}
<3>伝送フェーズ
<4>書き込み
フェーズ1:SCCBプロトコルは複数のSlaveに転送ができるため、Slaveの番号が伝える必要があります。実際のIDアドレスは8bitで、bit7~bit1はSlaveの番号ですが、0~127のトータル128のSlaveに転送が可能です。bit0はSlaveにデータを書き込み(0)か読み取り(1)かを示しています。9bit目はDon't
careビット(上図Xのビット)です。例えば、OV7670の場合、Masterから 8bitのデータを受信した後、SIO_C=1の期間にSlaveはSIO_DピンにLOWをセットします。この間、MasterはSIO_Dのレベル情報を読み取って判断する、LOWレベルを読み取った場合は、Slaveはフェーズ1の最初8bitを正常受信したことを示して、送信は成功します。それ以外の場合、送信は失敗します。
フェーズ2:データが書き込まれるレジスタの番号をスレーブに送信します。レジスタの番号は、OVセンサーのデータシートに記載されています。レジスタの番号も 8bitのデータです。
同様に、フェーズ2の9bit目もDon't careビットであり、このbitの説明はフェーズ1と同じです。
u8 SCCB_WR_Byte(u8 dat) { // 一つフェーズを書き込み
u8 j, res;
for (j = 0; j < 8; j++) {
if (dat&0x80) SCCB_SDA = 1;
else SCCB_SDA = 0;
data<<=1;
delay_us(50);
SCCB_SCL = 1;
delay_us(50);
SCCB_SCL = 0;
}
SCCB_SDA_IN(); // 或いはpinMode(SDA, INPUT); Slaveは値をセット可能
delay_us(50);
SCCB_SCL = 1; // SCLをHIGHにする、Slaveはデータを受信した後、SDAをLOWに
delay_us(50);
if (SCCB_READ_SDA) res = 1; // SDAはHIGHの場合、送信失敗
else res = 0; // 送信成功
SCCB_SCL = 0;
SCCB_SDA_OUT(); // あるいは pinMode(SDA, OUTPUT);
Return res;
}
三つフェーズを書き込みの関数:
u8 SCCB_WR_Reg(u8 reg, u8 data) {
u8 res = 0;
SCCB_Start();
If (SCCB_WR_Byte(SCCB_ID)) res = 1; // OV7670の場合は0x42
delay_us(100);
if (SCCB_WR_Byte(reg)) res = 1;
delay_us(100);
if (SCCB_WR_Byte(data)) res = 1;
SCCB_Stop();
return res;
}
<5>読み取り操作
Slaveのレジスタから 1 バイトのデータを読み取る時、次の 2 つのデータ送信プロセスが必要です。
①2 フェーズ書き込み送信プロセス:MasterからSlaveに2フェーズを送信します。最初のフェーズは、スレーブの ID 番号を示します。 2 番目のフェーズは、スレーブのどのレジスタから読み取るかを示します。
NAを送信するために、MasterはSIO_DをHIGHにセットしたままで、SIO_CをLOWからHIGHに変更してからLOWに戻る必要があります。
void SCCB_No_Ack(void) {
delay_us(50);
SCCB_SDA = 1;
SCCB_SCL = 1;
delay_us(50);
SCCB_SCL = 0;
delay_us(50);
SCCB_SDA = 0;
delay_us(50);
}
2フェーズを読み取り関数
u8 SCCB_RD_Byte(void) {
u8 temp = 0, j;
SCCB_SDA_IN();
for (j = 8; j > 0; j--) {
delay_us(50);
SCCB_SCL = 1;
temp = temp << 1;
if (SCCB_READ_SDA) temp++;
delay_us(50);
SCCB_SCL = 0;
}
SCCB_SDA_OUT();
return temp;
}
レジスタから読み取り関数:
u8 SCCB_RD_Reg(u8 reg) {
u8 val = 0;
SCCB_Start();
SCCB_WR_Byte(SCCB_ID);
delay_us(100);
SCCB_WR_Byte(reg);
delay_us(100);
SCCB_Stop();
SCCB_Start();
SCCB_WR_Byte(SCCB_ID|0x01);
delay_us(100);
val = SCCB_RD_Byte();
SCCB_No_Ack();
SCCB_Stop();
return val;
}




0 件のコメント:
コメントを投稿