距離センサとのIFをI2Cで行いました。距離センサは「MTOF171000C0」はRxDの操作でI2Cから切り離せて、複数のセンサを選択するCS信号として扱えると記載されています。ネット内ではTxDという説もありますが、どちらを操作してもCSとして機能しません
だまされた感はありますが、1ケであれば問題なく使えますし、クロック信号線に双方向バスバッファ(PCA9515Aなど)挿入して複数センサを扱うこともできます
ここでは、センサ1ケを対象にしたI2C通信例を説明します。通信仕様はいかのシーケンスに従います
・_gDistStateをenDistState_SndCmdにセットしてReadData関数をコールして読込みを開始します
・enDistState_SndCmd:バス解放・マスタ通信状態であればSST0をセットし、スタートコンディションを生成します(①)
・enDistState_SndCmdsStaWait:スタートコンディションを生成したら、シフトレジスタへスレーブアドレスを書込みます(②)
・enDistState_SndCmdWait:スレーブアドレスとコマンドが送信されるのを待ちます
・_I2c_Int関数のコメント欄③④⑤⑥と割込み内で処理されます。
・③は、スレーブアドレス送信に対するスレーブからのACK応答
・④は、ACK後のコマンド送信
・⑤は、コマンド送信に対するスレーブからのACK応答
・⑥は、⑤の応答で送信完了のフラグがセットされる
・enDistState_RcvDat:データ受信シーケンスのスタートコンディションをSST0をセットし生成します(⑦)
・enDistState_RcvDatStaWait:スタートコンディションを生成したら、シフトレジスタへスレーブアドレスを読込み条件にして書込みます(⑧)。この時データの読込み先ポインタを渡します(ここに受信データが格納されます)
・enDistState_RcvDatWait:_I2c_Int関数のコメント欄⑨➉⑪と割込み内で処理され、受信データが読込み先ポインタに格納されます
・外部からの完了判定は戻り値か_gDistState がenDistState_Standbyとなったら完了です
ReadData関数のコールはmain関数から連続でコールしてください
//*************************
// 距離センサタイミング
//*************************
typedef enum
{
enDistState_Standby = 0, // 待機中
enDistState_SndCmd, // コマンド送信
enDistState_SndCmdsStaWait, // スタートコンディション生成待ち
enDistState_SndCmdWait, // コマンド送信完了待ち
enDistState_RcvDat, // データ受信
enDistState_RcvDatStaWait, // スタートコンディション生成待ち
enDistState_RcvDatWait, // データ受信完了待ち
enDistState_Error // エラー
} DIST_SENSOR_STATE;
static DIST_SENSOR_STATE _gDistState = enDistState_Standby;// 距離センサ読取りステート
static uint8_t gRcvData[ 2 ]; // 受信データ
//************************************************************************************************
// 機能概要:1つの距離センサのデータを読込む
// 引数 :なし
// 戻り値 :ステート
// 備考 :
//************************************************************************************************
static SENSOR_STATE __near ReadData( void )
{
switch( _gDistState )
{
case enDistState_Standby: // 待機中
break;
case enDistState_SndCmd: // コマンド送信
/* ---< バス解放・マスタ通信状態の場合 >--- */
if(( IICBSY0 == 0 ) || ( MSTS0 == 1 ))
{
STT0 = 1U; // ① スタートコンディション生成
_gDistState = enDistState_SndCmdsStaWait;
}
/* ---< バス解放・マスタ通信状態でないならエラー >--- */
else
{
_gDistState = enDistState_Error;
}
break;
case enDistState_SndCmdsStaWait: // スタートコンディション生成待ち
/* ---< スタートコンディション移行検出 + スタートコンディション検出 >--- */
if(( STD0 == 1 ) && ( MSTS0 == 1 ))
{
/* ---< コマンド送信 >--- */
_gpTxData = _gCmd; // コマンド送信データポインタセット
_gTxDataCount = sizeof( _gCmd ); // コマンド送信データ数セット
IICA0 = ( 0x52 << 1 ) & 0xFE; // ② シフトレジスタへスレーブアドレス書込み
_gStatus = 1; // マスター動作中
_gDistState = enDistState_SndCmdWait;
}
break;
case enDistState_SndCmdWait: // スレーブアドレスとコマンド_gCmdの送信完了待ち
switch( _gStatus )
{
case 0: // ⑥送信完了
_gDistState = enDistState_RcvDat;
break;
case 1:
/* Do Nothing */ // マスター動作中なので待つ
break;
case 2: // エラーセット(Ack受信できず)
default:
_gDistState = enDistState_Error;
break;
}
break;
case enDistState_RcvDat: // データ受信
/* ---< バス解放・マスタ通信状態の場合 >--- */
if(( IICBSY0 == 0 ) || ( MSTS0 == 1 ))
{
STT0 = 1U; // ⑦ スタートコンディション生成
_gDistState = enDistState_RcvDatStaWait;
}
/* ---< バス解放・マスタ通信状態でないならエラー >--- */
else
{
_gDistState = enDistState_Error;
}
break;
case enDistState_RcvDatStaWait: // スタートコンディション生成待ち
/* ---< スタートコンディション移行検出 + スタートコンディション検出 >--- */
if(( STD0 == 1 ) && ( MSTS0 == 1 ))
{
/* ---< データ受信 >--- */
_gpRxData = gRcvData; // 受信データポインタ
_gRxDataLen = sizeof( gRcvData); // 目標受信データ数
_gRxDataCount = 0U; // 受信データ数
IICA0 = ( 0x52 << 1 ) | 0x01; // ⑧ シフトレジスタへスレーブアドレス書込み
_gStatus = 1; // マスター動作中
_gDistState = enDistState_RcvDatWait;
}
break;
case enDistState_RcvDatWait: // データ受信完了待ち
switch( _gStatus )
{
case 0: // ⑪
// _I2c_SetData( Name, gRcvData);
_gDistState = enDistState_Standby;
break;
case 1:
/* Do Nothing */ // マスター動作中なので待つ
break;
case 2: // エラーセット(Ack受信できず)
default:
_gDistState = enDistState_Error;
break;
}
break;
case enDistState_Error: // エラー
default:
_gDistState = enDistState_Error;
break;
}
return _gDistState;
}
#pragma interrupt _I2c_Int( vect = INTIICA0 )
//************************************************************************************************
// 機能概要:I2C割込
// 引数 :なし
// 戻り値 :なし
// 備考 :
//************************************************************************************************
static void __near _I2c_Int( void )
{
/* ---< 多重割込許可 >--- */
EI(); // 多重割込許可
/* ---< マスタ通信状態でないなら戻る >--- */
if( MSTS0 != 1U )
{
return;
}
//*************************
// アドレス送信完割込み
//*************************
if( STD0 == 1 ) // スタートコンディション検出済(アドレス転送期間)
{
/* ---< アドレスに対するACK受信済 >--- */
if( ACKD0 == 1 ) // ③⑤
{
//*************************
// マスタ送信
//************************* // Address + Write でアドレス送信完了
if( TRC0 == 1 )
{
// アドレス送信後のデータ書込みの1バイト目はここで送信するが、2バイト目以降は STD0==0 となっているので
// 下のマスター送信で送信される
// Data0 の1ビット目の転送時に STD0=0 とされる
// Address(W) + Data0 + Data1 ・・・
if ( _gTxDataCount > 0 )
{
IICA0 = *_gpTxData; // ④ スレーブへデータ送信
_gpTxData++; // 送信データポインタ更新
_gTxDataCount--; // 送信データ数減算
}
else
{
_gStatus = 0; // ⑥ 送信完了
}
}
//*************************
// マスタ受信開始
//************************* // Address + Read でアドレス送信完了
else
{
WTIM0 = 0; // 8クロック目ウエイトセット
IICA0 = 0xFF; // ウエイト解除し、受信状態にセット
}
}
/* ---< アドレスに対するNACK受信済 >--- */
else
{
SPT0 = 1; // ストップコンディション生成
_gStatus = 2; // エラーセット(Ack受信できず)
}
}
//*************************
// データ送受信完割込み
//*************************
else
{
//*************************
// マスタ送信
//*************************
if( TRC0 == 1 )
{
/* ---< Ack受信 >--- */
if ( ACKD0 == 1 )
{
if( _gTxDataCount > 0 ) // 送信データ残の確認
{
IICA0 = *_gpTxData; // 送信データセット
_gpTxData++; // 送信データポインタ更新
_gTxDataCount--; // 送信データ数減算
}
else
{
_gStatus = 0; // 送信完了
}
}
/* ---< Nack受信 >--- */
else
{
SPT0 = 1; // ストップコンディション生成
_gStatus = 2; // エラーセット(Ack受信できず)
}
}
//*************************
// マスタ受信開始
//*************************
else
{
/* ---< 受信データ残がある場合 >--- */
if( _gRxDataCount < _gRxDataLen )
{
*_gpRxData = IICA0; // ➉ 受信データセット
_gpRxData++; // 受信データポインタ更新
_gRxDataCount++; // 受信データ数加算
/* ---< 受信完了 >--- */
// 送信状態(TRC0=1)で,9クロック目ウエイト期間中にWREL0ビットを1にセットした場合,SDAA0 ラインがハイインピーダンスになる → スレーブのウエイト要求を受け付けられる
if( _gRxDataCount == _gRxDataLen )
{
ACKE0 = 0; // 最終データのNACK生成
WTIM0 = 1; // 9クロック目ウエイトセット
WREL0 = 1; // ウエイト解除
}
/* ---< 受信継続 >--- */
else
{
ACKE0 = 1; // ACK送信
WREL0 = 1; // ウエイト解除
}
}
else
{
SPT0 = 1; // ⑪ ストップコンディション生成
_gStatus = 0; // 受信完了
}
}
}
}