ArduinoのEEPROMアクセス、「EEMEM」について
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
| 固定リンク
「電子工作」カテゴリの記事
- ひさしぶりのイベントだったけど・・・「ピコピコ・スイッチ」破損(2021.12.13)
- 顕微鏡用LEDリングライトのLED、そろそろ交換か(2021.09.27)
- 可変抵抗器の「陽極酸化」(2021.09.22)
- 弾帯状になったQIコネクタのコンタクトピンを・・・(2021.08.27)
- AD620を使った計装アンプとシミュレーテッド・インダクタを使ったノッチフィルタ(2021.08.16)
「Arduino」カテゴリの記事
- ATtiny1614:タイマレジスタの初期設定を見る(2026.01.06)
- ラジオペンチさんの「ダイソーのゆらゆらLEDキャンドルライト」#2(2025.09.15)
- ラジオペンチさんの「ダイソーのゆらゆらLEDキャンドルライト」(2025.09.11)
- ATtiny402サンプル:"Wire.h"を使わずI2Cで液晶表示 AQM1602だと(2025.09.09)
- ATtiny402サンプル:I2Cで液晶表示 SCL周波数を設定できるようにしたら(2025.09.09)


コメント
EEMEMの挙動、なかなか不可思議です。
http://igarage.cocolog-nifty.com/blog/2022/08/post-ab8b48.html
Arduino-UNOでパルスジェネレータを作ってみた
このスケッチの中でEEMEMを使っているのですが、EEMEMで指定する順番を変えても、願った並びにすることができません。
また、不要なEEMEMデータは実値としてEEPROMに配置されません。
プログラムが動いた時のアクセスを見ているようなのです。
EEMEMで名称を確保して、それをテーブルに配置します。
しかし、実際にアクセスする動きがないと、EEPROMエリアにそのデータが出てきません。
EEMEMじゃなく、固定長のデータにして先頭からの順番でアクセスするほうが、安心できそうです。
その例↓
http://igarage.cocolog-nifty.com/blog/2020/05/post-8a04e0.html
投稿: 居酒屋ガレージ店主(JH3DBO) | 2022年8月 7日 (日) 08時56分