仕様としては、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の品種を使っているが、ベースマシンのデータ保存用ならそんなには必要ない。
0 件のコメント:
コメントを投稿