google-site-verification: google3bd66dd162ef54c7.html

ArduinoでI2Cの外付けEEPROMを使う

 Arduinoで作りたい物が無くなってしまいました。いや本当は雷センサーを仕上げたいのですが、当地では雷がほとんど発生していないのでデバッグが全く出来ないでいます。まあ夏になるまでには激しい雷雨の日があるんでしょうが、いつになることやらです。

 で、こういう時には将来に向けた準備をしましょう。ということで、買ったままになっていたI2C接続のEEPROMを動かしてみることにしました。

▼I2C EEPROM 24LC64
64k I2C EEPROM 24LC64
 容量は64kビット、つまり8kバイトです。MICROCHIP製で、以前秋月で買っておいた物です。

 Arduino UNOのCPUのATmega328Pには1kバイトのEEPROMが入っていて、不揮発な記憶領域として重宝します。でも大量にデーターを記録したい場合などは容量不足になるので、こういう外付けチップを使うと便利です。

▼回路図
ArduinoへI2C EEPROM接続回路
 Arduino UNOにI2C EEPROMを接続した回路です。文章で説明してもいいのでが、回路図書いたほうが間違いが無いです。

▼ブレッドボードで動かしてみる
ブレッドボード

 ここで必要になるのがテスト用のプログラムです。ネットを探すと先人の方が作られた作品がいろいろ出て来ますが、それらを参考に自分の好みに合わせて作ってみました。

▼I2C EEPROM動作確認用のスケッチ

/*
* I2C EEPROMの読み書きテスト
* 対応素子:24LC32, 24LC64, 24LC128, 24LC256, 24LC512
* 2015/06/24 ラジオペンチ http://radiopench.blog96.fc2.com/
*/

#include <Wire.h> //I2C ライブラリ

unsigned int startADR = 0x0000;
unsigned int endADR = 0x1FFF; // アドレス上限指定 (24LC64なら0x1FFF)
unsigned int ADR;
byte data;

void setup() {
Wire.begin();
Serial.begin(9600);

/*   // EEPROMに値を書き込みたい場合はコメントアウトを外す
Serial.print("Writing");
for (ADR = startADR; ADR <= endADR; ADR++) { // 全アドレス範囲に
data = ADR >> 3; // アドレスを適当に細工してデーターを作る
i2cEEPROM_write( 0x50, ADR, data); // データーを書き込む(アドレス/256の値)
if ((ADR & 0xFF) == 0) {
Serial.print('.'); // 書き込み進行中表示
}
}
*/ // ここまで

Serial.println();
Serial.println("EEPROM dump");

for (ADR = startADR; ADR <= endADR; ADR++) { // 全アドレス範囲をダンプ
if ((ADR & 0x00FF) == 0x00) { // 256バイト毎に
Serial.println(); // 一行開ける
}
if ((ADR % 16) == 0) { // 行の先頭なら
printADR(ADR); // アドレス表示
}
data = i2cEEPROM_read(0x50, ADR); // 外付けEEPROMから読み出し
Serial.print(data >> 4, HEX); // 上位4ビットを16表示
Serial.print(data & 0x0F, HEX); // 下位4ビット
Serial.print(" "); // データ間にスペース入れ
if ((ADR % 16) == 15) { // 行末なら
Serial.println(); // 改行
}
}
}

void loop() { // 無限ループで停止
}

void i2cEEPROM_write(int i2cADR, unsigned int eeADR, byte data ) {
Wire.beginTransmission(i2cADR); // i2cアドレス指定
Wire.write((int)(eeADR >> 8)); // EEPROM内アドレス指定 MSB
Wire.write((int)(eeADR & 0xFF)); // LSB
Wire.write(data);
Wire.endTransmission();
delay(5); // 書き込み完了待ち
}

byte i2cEEPROM_read( int i2cADR, unsigned int eeADR ) {
Wire.beginTransmission(i2cADR); // i2cアドレス指定
Wire.write((int)(eeADR >> 8)); // EEPROM内アドレス指定 MSB
Wire.write((int)(eeADR & 0xFF)); // LSB
Wire.endTransmission();
Wire.requestFrom(i2cADR, 1); // 1バイトデータリクエスト
while (Wire.available()) { //
data = Wire.read(); // データ受信
}
return data;
}

void printADR(unsigned int a) { // アドレスを4桁表示
String b = "";
if (a < 0x1000) {
b = "0";
}
if (a < 0x100) {
b = "00";
}
if ( a < 0x10) {
b = "000";
}
Serial.print(b);
Serial.print(a, HEX);
Serial.print(" ");
}

 プログラムの最初のコメントアウトしてある部分(18~7行)でEEPROMにデーターを書き込んでいます。書き込むデータはアドレスの値に細工して作っています(21行)が、ここはいろいろな方法(式)を試すと面白いと思います。なお1バイト書くのに約5msかかるので、8kバイトのチップ全体に書き込むには40秒くらいかかります。

 プログラムの後半の部分でEEPROMの全データーをシリアルにダンプするようになっています。

▼表示例
EEPROM dump

0000 00 00 00 00 00 00 00 00 01 01 01 01 01 01 01 01
0010 02 02 02 02 02 02 02 02 03 03 03 03 03 03 03 03
0020 04 04 04 04 04 04 04 04 05 05 05 05 05 05 05 05
0030 06 06 06 06 06 06 06 06 07 07 07 07 07 07 07 07
0040 08 08 08 08 08 08 08 08 09 09 09 09 09 09 09 09
0050 0A 0A 0A 0A 0A 0A 0A 0A 0B 0B 0B 0B 0B 0B 0B 0B
0060 0C 0C 0C 0C 0C 0C 0C 0C 0D 0D 0D 0D 0D 0D 0D 0D
0070 0E 0E 0E 0E 0E 0E 0E 0E 0F 0F 0F 0F 0F 0F 0F 0F
0080 10 10 10 10 10 10 10 10 11 11 11 11 11 11 11 11
0090 12 12 12 12 12 12 12 12 13 13 13 13 13 13 13 13
00A0 14 14 14 14 14 14 14 14 15 15 15 15 15 15 15 15
00B0 16 16 16 16 16 16 16 16 17 17 17 17 17 17 17 17
00C0 18 18 18 18 18 18 18 18 19 19 19 19 19 19 19 19
00D0 1A 1A 1A 1A 1A 1A 1A 1A 1B 1B 1B 1B 1B 1B 1B 1B
00E0 1C 1C 1C 1C 1C 1C 1C 1C 1D 1D 1D 1D 1D 1D 1D 1D
00F0 1E 1E 1E 1E 1E 1E 1E 1E 1F 1F 1F 1F 1F 1F 1F 1F

0100 20 20 20 20 20 20 20 20 21 21 21 21 21 21 21 21
0110 22 22 22 22 22 22 22 22 23 23 23 23 23 23 23 23
0120 24 24 24 24 24 24 24 24 25 25 25 25 25 25 25 25

以下、指定番地までダンプ

 EEPROMの全領域をダンプ表示するプログラムは、何か問題が起きた時の調査ツールとして役立つと思います。

 このプログラムは24LC64用に書いてありますが、アドレシング方法が同じ24LC32, 24LC128, 24LC256, 24LC512でも使えるはずです。但しアドレス上限を指定している endADRの値(10行目)は修正が必要です。

▼I2Cバスの波形
I2Cバス波形
 1バイト読み出す時の波形で、上がクロック(SCL)、下がデータ(SDA)波形。読み出しに500μsちょっとかかっています。

▼波形拡大
波形拡大
 クロック周期は10μs、つまり100kHzで動いていました。この速度にプルアップ抵抗の1kΩは充分に効いていて、綺麗な波形です。

◆まとめ
 ということで、I2CインターフェイスのEEPROMを動かすことが出来ました。

 このチップにはページ書き込みや連続読み出し機能など、高速で読み書きを行う機能が付いています。でもそういうのは、めったに使うことは無さそうなので、テストプログラムは省略しました。本当にそういう機能が必要になった時にプログラムを作れば充分だと思います。またArduinoで動かす場合、素子の速度の限界まで使い倒すなんてことはあまりやらないと思います。
関連記事

コメントの投稿

管理者にだけ表示を許可する

外付EEPROMへの書き込みについて

お世話になります。

arudinoでEEPROMへの書き込み方法を検索してたどり着きました!

ラジオペンチさんのスケッチ、18~27行での書込みも試して、
動くことを確認しました。

これは、1つづつ桁が上がっていきますが、
1Kバイトほどの任意のデータを書き込みたいと思っています。
この場合、どのようにすればよいでしょうか。

現在、その任意のデータは、テキストファイルにて、ダンプリストの状態になっています。

ご指導いただけないでしょうか。
よろしくお願いします。

re:外付EEPROMへの書き込みについて

岩倉さん、おはようございます。

大きなサイズのデーターをEEPROMに書くということですね。データーを一つずつ取り出して書き込むと判りやすいですが、そのデーターをどこから持ってくるかが問題ですよね。

実際にやったことがないので以下は想像ですが、

1.1kバイトなら変数領域のサイズの2kバイト以下なので「配列の変数の初期値として定義する」のが簡単だと思います。例えば下記
byte data[]={0x00, 0x01, 0x03, ,};

2.PROGMEMを使ってデータをプログラム領域(フラッシュメモリ)に置く。
 これだとフラッシュメモリのサイズである約30kバイトまでいけると思います。もちろんプログラムと領域の取り合いになります。

3.シリアルポートなど外部からデーターを読み込んで逐一書き込みを行う。

こんなとこだと思います。具体的に書けないですみません。

No title

ラジオペンチさん、ありがとうございます!

恐らく、1の方法が簡単そうですね。
いまある、テキストのファイルを、うまく編集して、
0x**,0x**という形にして、
{}内にコピペすればできるかもなので、さっそくやってみます!

また結果を報告します!
ありがとうございました!

No title

ラジオペンチさん

やってみました…が、
12行目にbyte data[]={0x00, 0x01, 0x03};
と入れましたが、そもそも文法を理解していないため
進めませんでした…
21行目も触る必要がありそうですが、どう手を付けていいのか
わかりません。

もう少しご教授していただけないでしょうか。
よろしくお願いします。

re:岩倉さん

この前のお返事に書いた変数名のdataは、既にプログラムで使われていたので判りにくくなってました。

要は最初に配列に値を定義しておいて、それを順にforループで読み出して、EEPROMに書けば大丈夫です。

サンプルプログラムを下記に置いておきますので試してみて下さい。細かく確認していませんが、たぶん動くと思います
http://blog-imgs-76.fc2.com/r/a/d/radiopench/20150629.txt

なお、データーがきっちり1024バイトになっているのを想定したプログラムになっているので、違っていたら値を直して下さい。
矛盾した値になっていてもプログラムは指定されたとおりに走るのでご注意下さい。

No title

ラジオペンチさん

ありがとうございます!
いただいたスケッチで無事に書けました!

書き込み後のダンプ表示も確認するために、
とても便利でした。

私のような、超初心者の突然のお願いも快くご回答いただいて
感謝します。

ありがとうございました!!!

岩倉さん今晩は

連絡ありがとうございます。

うまくいったみたいで良かったです。
カレンダー
06 | 2017/07 | 08
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 - - - - -
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード