1MbitのI2C EEPROMのAT24C1024Bの手持ちがあったのでテストしてみた。
仕様としては、I2C接続で電源電圧は2.5V~5.5VなのでArduinoでもNucleoでも気軽に使える。
書き込みはバイト単位、ページ単位、読み込みはランダムリードとシーケンシャルリードができる。
メモリの構成は、512Page × 256Byteになっていてアドレス指定は17bitで行う。
バイト単位の書き込み
1byte目 デバイス・アドレス ( 0x1010 | A2 | A1 | P0 | W )
2byte目 上位アドレス
3byte目 下位アドレス
4byte目 書き込みデータ
となっていて、1byte目のデバイスアドレスは、0x1010は固定、A2/A1はピンの接続と合わせて指定する(1個だけ使う場合はGNDに落として0を指定すると楽)。アドレス17bitのうち最上位1bitをP0で指定する。
バイト単位の読み込み
読み込みの場合は書き込みの1~3byte目と同じものをWモードで送信してアドレスを指定。4byte目のデータは送らずに、再びSTARTコンディションにしてRモードでデバイスアドレスを送信するとデータが返ってくる仕様。
Arduino
配線図
デバイスアドレスのA1/A2はGNDに落とし、I2CのSCL、SDAは1kΩでプルアップした。
ライブラリはArduinoのPlaygroundの「Arduino AT24C1024 I2C EEPROM Library」を使わせてもらった。(バイト単位の読み書きのみに対応)
http://playground.arduino.cc/Code/I2CEEPROM24C1024
https://github.com/jwhiddon/AT24C1024
ExampleのAT24C1024_EEPROM_Benchmarkをそのまま動作させることができた。全アドレスを読み書きするのでシリアル・コンソールにしばらく何も表示されないが、少し待てば「.」が表示されていく。
シリアル出力結果
AT24C1024 EEPROM Library Benchmark Sketch
--------------------------------
Write By Byte Test:
Writing data:...........................DONE
Total Time (seconds): 722
Write operations per second: 181
--------------------------------
--------------------------------
Read By Byte Test:
Reading data:..
Address: 9265 Should be: 25 Read val: 255
.........................DONE
Total Test Time (secs): 82
Read operations per second: 1598
Total errors: 1
--------------------------------
書き込みは181Byte/s、読み込みは1,598Byte/sで、1バイト読み書きに失敗したようだ。
I2C通信のようす
書き込み
ch1:SDA ch2:SCL
読み込み
Nucleo F401RE(mbed)
配線図
こちらも1kΩでプルアップ。
ライブラリはKenji Araiさんの「AT24C1024」ライブラリ(
https://developer.mbed.org/users/kenjiArai/code/AT24C1024/)を使わせてもらった。こちらはページ単位の読み書きにも対応している。
テスト・プログラム main.cpp
#include "mbed.h"
#include "AT24C1024.h"
I2C i2c(D14, D15); // SDA, SCL
AT24C1024 at24c1024(i2c); // Atmel 1Mbit EE-PROM
DigitalOut led1(LED1);
int main()
{
printf("\r\n*** AT24C1024 Test ***\r\n");
// Byte Read/Write
//
uint8_t dt = 0x55;
printf("Byte Write: %02x\r\n", dt);
at24c1024.write(0, dt); // write addr=0 data=dt
wait_ms(5);
dt = at24c1024.read(0); // read addr=0
printf("Byte Read: %02x\r\n", dt);
// Page Read/Write
//
uint8_t eep_buf[258];
for (int i = 0; i < 256; i++) {
eep_buf[i] = i;
}
printf("Page Write: 0..255\r\n");
AT24C_STATUS status = at24c1024.write_page(0x1ff00, eep_buf, sizeof(eep_buf));
wait_ms(5);
printf("Status: %d\r\n", status);
printf("Page Read:\r\n");
status = at24c1024.read_page(0x1ff00, eep_buf, sizeof(eep_buf));
printf("Status: %d\r\n", status);
for (int i = 0; i < sizeof(eep_buf); i++) {
printf("%d ", eep_buf[i]);
}
printf("\r\n");
while(1) {
led1 = !led1;
wait(0.2);
}
}
AT24C1024のWriteはDATASHEETを見ると5msかかるようなのでwait_ms(5)を入れている。waitをかけないと読み込みに失敗する。また、ページ単位の読み書きのバッファ、はメンバ関数内部でI2C通信用に2バイト使うので258バイト確保する必要がある。データはインデックス0から埋める。
<追記:2016.11.25>
write_page()とread_page()はエラーステータス(AT24C_STATUS)を返しますが、I2C通信がうまくいったかどうかは見ない仕様のようです。AT24C_OK = 0が返ってきても通信が失敗している場合もあります。
</追記>
I2C通信のようす
ch1:SDA ch2:SCL
メモ:
SDカードに比べるとR/Wの速度は遅いが、実装面積が節約できるし値段も安い。1Mbitの品種を使っているが、ベースマシンのデータ保存用ならそんなには必要ない。