動作環境
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の時に入出力方向を変更」として一貫性を持たせている。
入出力方向の切替時にglitchは見られる。
関連 http://electronics.stackexchange.com/questions/286564/i2c-ack-bit-glitch