ArduinoのEEPROMを使う上での注意点。
EEPROMに置いたデータを16進ダンプした時、「むむ?」な事態に遭遇しました。
Arduino、EEPROMに不揮発性データを置くことができます。
その時に使うのが「EEMEM」。
たとえば
word EEMEM data0;
word EEMEM data1;
:
word EEMEM data9;
こんな具合に、順に記していけばdata0~9までEEPROM内のアドレスが得られます。
↓のように、EEPROMアドレスの増加を自分に勘定しなくてもよいわけです。
#define data0 0
#define data1 2 ←wordだから2進む
:
#define data9 18
1バイトデータだけでなく多バイトデータでも、うまく配置してくれますので数えミスがありません。
※参考
「eeprom.h」の中で
#define EEMEM __attribute__((section(".eeprom")))
「.eeprom」というAVRマイコンのメモリー領域に割り当て
よっと指示されるわけです。
で、このEEMEMを使って配置したEEPROM内のデータ、これ、どういう
わけか並べた順にならないのです。
普通だと、列記した順に先頭からアドレスが割り振られるんじゃないか
と考えます。
ところが・・・実際は逆順に。
このあたりを確かめてみました。
一つはEEMEMを使ってのアドレス割り付け。
もう一つがstructを使ってのアドレス確保です。
offsetof()を使って、構造体先頭からのアドレス増加分を得て、これを
EEPROMのアドレスとします。
~~~~~~~~~~~~~~~~~~~~~~~~~~
// EEMEMのテスト
// EEPROMの読み書きで必要なのはアドレス情報
// EEMEMで順に列記
word EEMEM ee0; // 0~3まで
word EEMEM ee1;
word EEMEM ee2;
word EEMEM ee3;
// structでデータを並べる (実体は無い)
struct eeprom{
word ss0; // 0~3まで
word ss1;
word ss2;
word ss3;
};
// eepromのwordデータをアクセスするマクロ(アドレスを返す)
#define EPADRSW(eep_word) (word *)offsetof(eeprom, eep_word)
// 書式付シリアル出力
void txprintf(const char *s, ...)
{
va_list vp;
char bff[80]; // バッファを確保
va_start(vp,s);
vsnprintf(bff,sizeof(bff),s,vp);
Serial.print(bff);
va_end(vp);
}
void setup() {
const char s[]="%04X:%4d\n"; // アドレスとデータ
word i;
Serial.begin(9600); // シリアル通信
for(i=0; i<4;i++){ // 4データ EEPROMに書き込み
eeprom_write_word(2*i, 1001+i); // データは1001から
}
txprintf(s, &ee0,eeprom_read_word(&ee0)); // ee0~3のアドレス
txprintf(s, &ee1,eeprom_read_word(&ee1));
txprintf(s, &ee2,eeprom_read_word(&ee2));
txprintf(s, &ee3,eeprom_read_word(&ee3));
Serial.println(); // 改行
txprintf(s, EPADRSW(ss0),eeprom_read_word(EPADRSW(ss0))); // ss0~3のアドレス
txprintf(s, EPADRSW(ss1),eeprom_read_word(EPADRSW(ss1)));
txprintf(s, EPADRSW(ss2),eeprom_read_word(EPADRSW(ss2)));
txprintf(s, EPADRSW(ss3),eeprom_read_word(EPADRSW(ss3)));
}
void loop() {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~
シリアルモニターした結果。
↓
0006:1004 ←EEMEMで記述した部分
0004:1003
0002:1002
0000:1001
0000:1001 ←structで
0002:1002
0004:1003
0006:1004
最初の4データ、「EEMEM」での書式では列記したのとは逆順にアドレス
が割り振られているのが見えています。
structで実体は無いデータを列記した場合は、書いた順序通りに現れます。
これ、データの名前でアクセスする分には何も問題ありません。
しかし、デバッグ時のときなど、EEPROMデータを16進ダンプして
データを見ようとした時、やはり記述した順に並んでいてほしいもの
です。
もう一つの注意点。
ArduinoのブートローダーはEEPROM内の初期化データを扱うことが
できません。
ですので、EEPROMデータの初期化は自前で行わなければなりません。
※AVRマイコンsectionの種類
・http://d.hatena.ne.jp/seinzumtode/20140719/1405789889
最近のコメント