2022年8月16日火曜日

SCCBバスプロトコル詳解と実装方法

 ■SCCB紹介

 SCCB (Serial Camera Control Bus) は、OmniVision社のシリアル カメラ バス プロトコルです。OV7670 などの OV で始まるカメラ モジュールは、SCCB プロトコルを使用します。I2C プロトコルと類似しているため、SIO_CSIO_DSCLSDAと呼びます。

 本文は2線式SCCBプロトコルの内容とプログラム実装を中心に解説します。

■回路図

 2線式SCCBに対して、SIO_CSIO_Dだけを接続すればよいです。

■プロトコルの内容とプログラム実装

2 線式 SCCB バス プロトコル解析

<1>送信開始フラグ: 送信 (データの読み取りまたは書き込み) ごとに、下図に従って SIO_C SIO_D に指定されたHIGH-LOWレベルを出力する必要があります。対応するレベルを受け取ると、Slaveは転送開始が判ります。次のように操作します。SIO_CHIGHのままでSIO_DHIGHからLOWに変換して、SIO_CLOWに戻ります。

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_CHIGHのままでSIO_DLOWからHIGHに変換します。 

void SCCB_Stop(void) {

  SCCB_SDA = 0;

  delay_us(50);

  SCCB_SCL = 1;

  delay_us(50);

  SCCB_SDA = 1;

  delay_us(50);

}

<3>伝送フェーズ

転送フェーズ(Transmission Phases)は、データ転送の基本単位です。9bitで構成しています、それぞれは、bit7bit09bit目のDon't careまたはNAです。Don't care ビットと NA ビットの意味は後で説明します。

<4>書き込み

Slave1バイトのデータを書き込みすることは1回書き込み操作と呼びます。1バイトのデータを書き込み時、SlaveID、対象レジスタ番号も伝える必要があるため、書き込み操作のプロセスは三つのフェーズ(Phase)が必要です。

フェーズ1SCCBプロトコルは複数のSlaveに転送ができるため、Slaveの番号が伝える必要があります。実際のIDアドレスは8bitで、bit7bit1Slaveの番号ですが、0127のトータル128Slaveに転送が可能です。bit0Slaveにデータを書き込み(0)か読み取り(1)かを示しています。9bit目はDon't careビット(上図Xのビット)です。例えば、OV7670の場合、Masterから 8bitのデータを受信した後、SIO_C=1の期間にSlaveSIO_DピンにLOWをセットします。この間、MasterSIO_Dのレベル情報を読み取って判断する、LOWレベルを読み取った場合は、Slaveはフェーズ1の最初8bitを正常受信したことを示して、送信は成功します。それ以外の場合、送信は失敗します。

フェーズ2:データが書き込まれるレジスタの番号をスレーブに送信します。レジスタの番号は、OVセンサーのデータシートに記載されています。レジスタの番号も 8bitのデータです。 同様に、フェーズ29bit目もDon't careビットであり、このbitの説明はフェーズ1と同じです。

フェーズ3:指定されたレジスタにデータを書き込みます。bit7bit0は、レジスタに書き込みたいデータです。9ビット目もDon't careビットです。

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; // SCLHIGHにする、Slaveはデータを受信した後、SDALOW

delay_us(50);

if (SCCB_READ_SDA) res = 1;  // SDAHIGHの場合、送信失敗

  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からSlave2フェーズを送信します。最初のフェーズは、スレーブの ID 番号を示します。 2 番目のフェーズは、スレーブのどのレジスタから読み取るかを示します。 

2フェーズ読み取り送信プロセス:Slaveからデータを読み取っています。フェーズ1は①のフェーズ1とほぼ同じですが、Slaveから読み取りから、bit01のほうをご注意ください。フェーズ2は転送データです。

したがって、SIO_Dにつながっているピンは入力モードに設定する必要があります。8bitのデータを読み取った後、データが正常に受信されたことをSlaveに伝えるために、Master1bitの応答信号(NA)Slaveに送信する必要があります。

NAを送信するために、MasterSIO_DHIGHにセットしたままで、SIO_CLOWから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;

}

ここまで、SCCBのレジスタ読み取り操作とレジスタ書き込み操作の関数SCCB_RD_RegSCCB_WR_Regを実装しました。この二つ関数を利用して、OVセンサーの指定されたレジスタへのデータを読み取りしたり、書き込みしたり、センサーの初期化ができました。



0 件のコメント:

コメントを投稿

シンプルロボットカーセットの使い方

■ マイコン :ESP3266-CH340  シンプルの案として、マイコンは安いESP8266-CH340開発ボードを選びました。該当マイコンもWIFI機能があります。  ドライバーダウンロード場所:    https://sparks.gogo.co.nz/ch340.html...