PSoCでI2C読み出し

PSoCでセンサICなどからデータを読み出す場合を考える。


以下では、I2Cブロックを I2C_1 という名前にしたものとする。
(PSoC Creatorめ! なんでC++でクラス化しないの?)


まず、読み出し完了まで同期待ちしてもよいなら次のようになる。

// 複数バイト読み出し
// devAddr: スレーブアドレス
// regAddr: サブアドレス
// length: バイト長
// value: 値を格納する領域の先頭
void I2CReadBytes(uint8 devAddr, uint8 regAddr, uint8 length, uint8 *value)
{
    uint8 i=0;
    I2C_1_MasterSendStart(devAddr, I2C_1_WRITE_XFER_MODE);
    I2C_1_MasterWriteByte(regAddr);
    I2C_1_MasterSendRestart(devAddr, I2C_1_READ_XFER_MODE);
    while (i++ < (length-1)) {
        *value++ = I2C_1_MasterReadByte(I2C_1_ACK_DATA);
    }
    *value = I2C_1_MasterReadByte(I2C_1_NAK_DATA);
    I2C_1_MasterSendStop();
}


しかし、組込みソフトで通信完了まで同期待ちしてるようではこの先心配である。
(同期待ちが許されるのはArduinoまでだよね! キャハハ! キモーイ!)
アドレス書き込みはともかく、データ読み出しは非同期にしたい。

// 複数バイト読み出し開始 (非同期)
// devAddr: スレーブアドレス
// regAddr: サブアドレス
// length: バイト長
// value: 値を格納する領域の先頭
// 戻り値: エラー状態
uint8 I2CReadBytesAsync(uint8 devAddr, uint8 regAddr, uint8 length, uint8 *value)
{
    // アドレスを書く
    I2C_1_MasterSendStart(devAddr, I2C_1_WRITE_XFER_MODE);
    I2C_1_MasterWriteByte(regAddr);
    
    // データ読み出し開始
    uint8 ret = I2C_1_MasterReadBuf(
        devAddr, value, length,
        I2C_1_MODE_COMPLETE_XFER | I2C_1_MODE_REPEAT_START);
    return ret;
}

// 複数バイト読み出し状態チェック
// 戻り値: 読み出し状態
uint8 I2CReadBytesWait()
{
    uint8 status;
    
    // ステータスを取得する
    status = I2C_1_MasterStatus();
    
    // 転送中か
    if(status & I2C_1_MSTAT_XFER_INP){
        return status;
    }
    // 最終のステータスを取得し、ステータスをクリアする
    status = I2C_1_MasterClearStatus();
    return status
}