PIC12F675でI2C接続のAT24C256Bにデータを書き込む練習の第二弾(第一弾はこちらに)。
データの送信が早すぎて、ACKが返って来ない場合には、EEPROMのデータ・シートに書かれている最大書き込み時間である約5msの待ちを入れてから次のデータを送るようにすればいいようだが、せっかくAcknowledge(ACK)かNot Acknowledge(NACK)かを返してくるのだから、それに対応した処理をするのも手かと思った。
ので、こんなコードにしてみた。
ret1:
I2C_Start();
retACK = I2C_Write_Byte(0xA0);
if(retACK==1){
I2C_Stop();
goto ret1;
}
retACK = I2C_Write_Byte(0x00);
retACK = I2C_Write_Byte(0x00);
retACK = I2C_Write_Byte(0xDD);
I2C_Stop();
NAK(このロジック・アナライザではNot Acknowledgeをこう表記する。)が返ってきたらもう一度Startからやり直すと、2度目はちゃんとACKが返っているのが分かる。
ただし、その間12msかかるという本末転倒な結果だ。
とりあえず1バイト分送信してみてからのACKなので、送信速度が遅ければその分の時間が無駄になるのも致し方ないところ。
これなら素直に5ms待った方が結果的には速いということになる。
「だいたい5msくらいかな」というあいまいさは無くて手順的には理屈に合っているんだけど。
この方法で0×0000番地に0xDD、0×0002番地に0xEE、0×0005番地に0xFFを書き込んだ結果、ちゃんと書き込めていることは確かなようだ。
ちなみに、ここまでのプログラムは参考にさせていただいたサイトのコードのままにI2Cの速度を初期設定で1kbpsとしていて、通常は100kbps程度(仕様ではこれが標準とされている。)のようなので、ずいぶん遅い設定になっている。
上のようにACK待ちがEEPROMの書き込み速度以上の時間を食ってしまうのはI2Cの速度が遅いためなので、100kbpsに設定して同様のプログラムを走らせてみたところ以下のような結果になった。
NAKを3回食らうことにはなるが、待ち時間は1.72msで済んでおり、3バイト書き込むのに要した時間は11msだった。
上ではACK待ちだけで12msかかっている。
なるほど、こうすればACK待ち処理を追加する意味が出てくるわけだ。
ただし、参考にさせていただいたサイトには、
I2C_SPEED is defined to be 1kbps. You can go up to a maximum of 100kbps speed when using 20MHz crystal with PIC12F675. If a lower crystal value is used then you should use lower value of i2c speed as well to avoid errors. For example, when a crystal value of 4MHz is used, then a safe value for I2C_SPEED is 1kbps and a maximum value of 10kbps can be used. HalfBitDelay value is always equal to 500/I2C_SPEED.
と書かれていて、最高100kbpsまでいけるけど、クロックが4MHzでは10kbps位が上限だとある。
仕様書にはHsモードで最大4.3Mpsという頼もしい値も書かれてはいるが、わざわざ高クロックの発振装置を追加してまで速度を稼ぐ使い道も無いように思うので、おとなしく10kbpsでの運用がいいのかもしれない。