LoginSignup
4
5

More than 5 years have passed since last update.

MSP430 > I2C > ソフトウェアI2Cでの実装 > SDAの方向制御のタイミング

Last updated at Posted at 2017-03-08
動作環境
MSP430
Tektronix TDS 2024C (200 MHz, 2GS/s)
とあるI2Cセンサ

とあるセンサのプロトコルは以下に記載。
http://qiita.com/7of9/items/d839e67c6650e012a8fd

code v0.1

MSP430でのソフトウェアI2Cで実装し、それらしいデータを読み取れる(波形がくずれない)ことを確認できたコードのsnippetは以下。

    int loop;
    // Raspberry Piで動作確認した状況を再現してみる (2017/03/08)

    // 1. 準備
    SDA_0_DIROUT;
    SCK_0_DIROUT;
    SDA_0_HIGH;
    SCK_0_HIGH;
    myDelay();
    myDelay();
    myDelay();

    // 2. start condition
    SDA_0_LOW;
    myDelay();
    SCK_0_LOW;
    myDelay();

    // 3. slave address
    char slvAdr = 0x28;
    bool bitVal;
    for(loop=0; loop<7; loop++) { // 7bit
        bitVal = (slvAdr & 0x40);
        SCK_0_LOW;
        if (bitVal) {
            SDA_0_HIGH;
        } else {
            SDA_0_LOW;
        }
        myDelay();
        SCK_0_HIGH;
        myDelay();
        slvAdr <<= 1;
    }

    // 4. Read-bit
    SCK_0_LOW;
    SDA_0_HIGH; // for read-bit
    myDelay();
    SCK_0_HIGH;
    myDelay();

    // 5. read ACK (ACK=0)
    SCK_0_LOW;
    SDA_0_DIRIN;
    myDelay();
    SCK_0_HIGH;
    bool isAck = is_SDA_0_High(); // read ACK
    myDelay();

    // 6a. read 1st data
    for (loop=0; loop<8; loop++) {
        SCK_0_LOW;
        if (loop == 0) {
            SDA_0_DIRIN;   
        }
        myDelay();
        SCK_0_HIGH;
        // TODO: read bit
        myDelay();
    }

    // 6b. send ACK (ACK=0)
    SCK_0_LOW;
    SDA_0_DIROUT;
    SDA_0_LOW; // ACK
    myDelay();
    SCK_0_HIGH;
    myDelay();

    // 7a. read 2nd data
    for (loop=0; loop<8; loop++) {
        SCK_0_LOW;
        if (loop == 0) {
            SDA_0_DIRIN;   
        }
        myDelay();
        SCK_0_HIGH;
        // TODO: read bit
        myDelay();
    }

    // 7b. send NAK (NAK=1)
    SCK_0_LOW;
    SDA_0_DIROUT;
    SDA_0_HIGH; // NAK
    myDelay();
    SCK_0_HIGH;
    myDelay();

    // 8. stop condition
    SCK_0_LOW;
    SDA_0_LOW;
    myDelay();
    SCK_0_HIGH;
    myDelay();
    SDA_0_HIGH;
    myDelay();

以下はマクロで組んでいるが、実コードでは再検討が必要。

  • SCK_0_LOW : SCKラインをdeassert
  • SDA_0_LOW : SDAラインをdeassert
  • SCK_0_HIGH : SCKラインをassert
  • SDA_0_HIGH : SDAラインをassert
  • SDA_0_DIRIN : SDAラインを入力方向に
  • SDA_0_DIROUT : SDAラインを出力方向に

myDelay()においては__delay_cycles(8);を使用し、delayを行う。

はまった点

SDA_0_DIRIN とSDA_0_DIROUT を実行するタイミング。
これが失敗すると、データ読み出しクロックにおいて、SDAラインがHレベルのままとなったり、奇数回目の通信において波形がくずれるなどの症状が見られた。

上記のコードにおいては「SCKラインがdeassertの時に入出力方向を変更」として一貫性を持たせている。

F0001TEK.png

入出力方向の切替時にglitchは見られる。
関連 http://electronics.stackexchange.com/questions/286564/i2c-ack-bit-glitch

4
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5