<EEPROM.h>を参照すると EEPROMClassが実際に呼びだされている。
read、writeの他、以下の定義が気になったので試してみました。
結論から書くと、read→get、write→putの置き換えで、構造体の操作の箇所のコードは短くなりますが、スケッチサイズは20バイトほど増えました。
自前の関数を作らなくていいので自分としては許容範囲。
EERef operator[]( const int idx ) { return idx; }
void update( int idx, uint8_t val ) { EERef( idx ).update( val ); }
template< typename T > T &get( int idx, T &t ){
EEPtr e = idx;
uint8_t *ptr = (uint8_t*) &t;
for( int count = sizeof(T) ; count ; --count, ++e ) *ptr++ = *e;
return t;
}
template< typename T > const T &put( int idx, const T &t ){
EEPtr e = idx;
const uint8_t *ptr = (const uint8_t*) &t;
for( int count = sizeof(T) ; count ; --count, ++e ) (*e).update( *ptr++ );
return t;
}
●書き換えた内容
読み込み(read→get)
byte* p = (byte*) &lightSet;
unsigned int adr = 0;
for (unsigned int i = 0; i < sizeof(lightSet); i++)
*p++ = EEPROM.read(adr++)
↓
EEPROM.get(0, lightSet);
byte* p = (byte*) &lightSet;
unsigned int adr = 0;
for (unsigned int i = 0; i < sizeof(lightSet); i++)
EEPROM.write(adr++, *p++);
↓EEPROM.put(0, lightSet);
sprintf_P(ch, PSTR( "%02X ") ,EEPROM.read(adr));↓
sprintf_P(ch, PSTR( "%02X ") , *EEPROM[adr]);
●追加(updateでEEPROMを0xFFで初期化)
// 0xFFで初期化
Serial.print("EEPROM初期化");
for(unsigned int adr = 0; adr < EEPROM.length(); adr++) {
EEPROM[adr].update( 0xFF );
}
Serial.println(" ->初期化完了");
添字でアドレスを指定して、updateの引数に値を指定する。updateはEERefのupdateを呼び出している。定義を見ると↓の様になっていて値が同じなら更新しない動作となっている。
EERef &update( uint8_t in ) { return in != *this ? *this = in : *this; }
書き込み回数の寿命が10万回なので、無駄な書き込みをしないように考慮しているんですね。
EEPROM.putも書き込みにはupdateを使っているので、こちらを使う方がよさそうです。
●最終的なソース
#include <EEPROM.h>
/* 制御用のパラメータ定義 */
struct LightSetting_t {
unsigned int offWaitSec; /* 消灯時間(sec) */
unsigned int border; /* 検出距離(cm) */
} lightSet;
/* EEPROM用の操作ボタン */
int statusPin2 = HIGH; /* 書き込み */
int statusPin3 = HIGH; /* 読み込み */
int statusPin4 = HIGH; /* ダンプ出力 */
int statusPin8 = HIGH; /* 初期化 */
/*
* 設定更新
*/
void updateSetting() {
if (LOW == digitalRead(4)) {
if (statusPin4 == HIGH) {
statusPin4 = LOW;
dumpEEPROM();
}
} else {
statusPin4 = HIGH;
}
if (LOW == digitalRead(3)) {
if (statusPin3 == HIGH) {
statusPin3 = LOW;
// EEPROM読み込み
EEPROM.get(0, lightSet);
Serial.println("設定値");
Serial.print("消灯時間(sec)=");Serial.println(lightSet.offWaitSec);
Serial.print("検出距離(cm) =");Serial.println(lightSet.border);
if (lightSet.offWaitSec == 0x0000 || 0xFFFF == lightSet.offWaitSec ) {
Serial.println("設定値初期化");
lightSet.offWaitSec = 10;
lightSet.border = 5;
Serial.print("消灯時間(sec)=");Serial.println(lightSet.offWaitSec);
Serial.print("検出距離(cm) =");Serial.println(lightSet.border);
}
}
} else {
statusPin3 = HIGH;
}
if (LOW == digitalRead(2)) {
if (statusPin2 == HIGH) {
statusPin2 = LOW;
// それぞれ+1する
lightSet.offWaitSec++;
lightSet.border++;
Serial.print("設定書き込み");
// EEPROM書き込み
EEPROM.put(0, lightSet);
Serial.println(" ->書き込み完了");
}
} else {
statusPin2 = HIGH;
}
if (LOW == digitalRead(8)) {
if (statusPin8 == HIGH) {
statusPin8 = LOW;
// 0xFFで初期化
Serial.print("EEPROM初期化");
for(unsigned int adr = 0; adr < EEPROM.length(); adr++) {
EEPROM[adr].update( 0xFF );
}
Serial.println(" ->初期化完了");
}
} else {
statusPin8 = HIGH;
}
}
void dumpEEPROM() {
unsigned int adr = 0;
unsigned int adrLength;
byte data;
char ch[6];
Serial.print(F("EEPROM size="));
Serial.println(EEPROM.length());
adrLength = 32; // 最初の32バイトまで表示
for(adr = 0; adr < adrLength; adr++) {
if ((adr % 16) == 0) {
sprintf_P(ch, PSTR("%04X:"), adr);
Serial.print(ch);
}
sprintf_P(ch, PSTR( "%02X ") , *EEPROM[adr]);
Serial.print(ch);
if ((adr % 16) == 15) {
Serial.println();
}
}
}
void setup() {
/* EEPROMのダンプ出力、読み込み、書き込み用のボタン */
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
Serial.begin(115200);
}
void loop() {
updateSetting();
delay(100);
}
0 件のコメント:
コメントを投稿