2016-08-11 160 views
0

我試圖使用標準Arduino EEPROM-Library例程EEPROM.put()將所有值從4個結構保存到ATMega328P EEPROM中,並通過EEPROM.get ()。如何將我的value_table中的所有值傳遞給這些函數?這是我的數據如何。如何將指針陣列中的值保存到EEPROM中的結構中

typedef struct EXAMPLE { 
    uint8_t part1[7][2]; 
    uint8_t part2[3]; 
} *ptr[5]; 


EXAMPLE VALUE_1 = {{ 
    {1, 8}, 
    {2, 9}, 
    {3, 10}, 
    {4, 11}, 
    {5, 12}, 
    {6, 13}, 
    {7, 14} 
}, 
    {15, 16, 17} 
}; 

在指針數組中組合了四個版本VALUE_1到VALUE_4。

struct EXAMPLE *value_table[] = {&VALUE_1, &VALUE_2, &VALUE_3, &VALUE_4}; 

這是我想到的,但收益率錯誤的結果。

EEPROM.put(0, &value_table); // 0 is first byte of EEPROM 
EEPROM.get(0, value_table); 

我想存儲的是位於VALUE_1 - VALUE_4中的值,以使它們持久。

我非常感謝每一個提示!

+2

指針可能會殺死你。如果我正確地閱讀,您已經告訴'put'寫入4個指針,而不是指針處的數據。 – user4581301

+0

是的,這可能是正確的。但是,必須有一種方法來獲得價值觀並將它們傳遞給'put'?像EEPROM.put(0,VALUE_1)這樣獨立寫入和讀取這些元素可以工作,但這不是正確的... – user3750030

+1

@ user3750030:不存在,它存儲你給它的數據。如果你給它4個指針,它將存儲4個指針(並且沒有數據)。它不知道'value_table'的內部結構是什麼,它只是獲得'sizeof(value_table)'並將很多字節存儲到EEPROM中。實際上,現在我強烈懷疑您的原始代碼僅存儲單個VALUE_1指針,而不是其他三個指針。很難從那些愚蠢的文檔中看出來。將它們分開存儲的問題有哪些?你仍然可以在指針數組上做一個'for'(查看我的代碼,它尖叫着「我」替換)。 – Ped7g

回答

0

只是猜測:

// writing (starting at some "eeprom_address" address) 
int eeprom_address = 0; 
EEPROM.put(eeprom_address + 0*sizeof(EXAMPLE), VALUE_1); 
EEPROM.put(eeprom_address + 1*sizeof(EXAMPLE), VALUE_2); 
EEPROM.put(eeprom_address + 2*sizeof(EXAMPLE), VALUE_3); 
EEPROM.put(eeprom_address + 3*sizeof(EXAMPLE), VALUE_4); 

// reading 
EEPROM.get(eeprom_address + 0*sizeof(EXAMPLE), VALUE_1); 
EEPROM.get(eeprom_address + 1*sizeof(EXAMPLE), VALUE_2); 
EEPROM.get(eeprom_address + 2*sizeof(EXAMPLE), VALUE_3); 
EEPROM.get(eeprom_address + 3*sizeof(EXAMPLE), VALUE_4); 

// plus set the value_table in the same way as before 
struct EXAMPLE *value_table[] = {&VALUE_1, &VALUE_2, &VALUE_3, &VALUE_4}; 

有沒有點到存儲指針到EEPROM,你應該只存儲數據值(但以結構化方式,讓你知道哪些字節屬於哪個數據項,並且可以讀取它們正確地轉換成目標變量)。

如果您想要使用單個結構,請執行struct EXAMPLE value_table[] = {VALUE_1, VALUE_2, VALUE_3, VALUE_4};。但是,這會將VALUE_1複製到value_table中,所以它會佔用兩倍的內存,因爲只有一個VALUE_1。

順便說一句,文件只是說「EEPROM.get(地址,數據)」沒有類型...這仍然是C/C++? :/ *皺眉*

文檔鏈接:get,put,也有struct的例子。

BTW:int僅作爲官方文件的副本地址,我會親自不要使用int爲當然的地址,突然我的計劃在某個遙遠的未來點檢查的Arduino變得更加遙遠。


for變種寫作:

constexpr size_t VALUES_N = 4; 
struct EXAMPLE *value_table[] = {&VALUE_1, &VALUE_2, &VALUE_3, &VALUE_4}; 
// writing (starting at some "eeprom_address" address) 
int eeprom_address = 0; 
for (size_t i = 0; i < VALUES_N; ++i) { 
    EEPROM.put(eeprom_address + i*sizeof(EXAMPLE), *(value_table[i])); 
} 

// reading 
for (size_t i = 0; i < VALUES_N; ++i) { 
    EEPROM.get(eeprom_address + i*sizeof(EXAMPLE), *(value_table[i])); 
} 
+0

我認爲它是C++,帶'get'和'put'是模板。請注意缺少尺寸參數。 – user4581301

+0

@ user4581301 hmm ...所以任何不知道里面發生了什麼的新手都會使用它來創建數以百萬計的自定義結構,想知道爲什麼代碼大小急劇上升(或者只是變得更大一些,取決於模板的寫法) ? \ *皺眉更*。哦,謝謝你的信息。 :) – Ped7g

+0

我環顧了一下頭部的副本,但找不到一個。 Arduino是一種嵌入式系統傻瓜(本身並不是一件壞事),所以編程和類型安全的簡易勝過了許多其他考慮因素。如果我建立一些安全的關鍵,那麼當工具鏈使我更難殺死某人時,我會喜歡它。 – user4581301

0

下載的Arduino和getput接過來一看。正如預期的那樣他們模板

template< typename T > T &get(int idx, T &t) 
template< typename T > const T &put(int idx, const T &t) 

因爲他們有模板定義類型的參數的引用,他們知道他們需要執行讀或寫EEPROM的大小和幾乎一切。

希望在某處下線put在寫入失敗時拋出異常,因爲我沒有看到任何throw或其他錯誤通知方法,但這不是關注點。

所以...

struct EXAMPLE *value_table[] = {&VALUE_1, &VALUE_2, &VALUE_3, &VALUE_4}; 

是4個指針結構,而不是結構本身的陣列。這意味着

sizeof(value_table); 

將是一個指針的大小的四倍,可能是一個Arduino上的16個字節。但是

EEPROM.put(0, &value_table); 

甚至不會寫這個。因爲它傳入一個指向value_table的指針,所有將被寫入的指針都是一個單獨的指針,由於數組的工作方式,它將是一個指向第一個條目的指針,它是指向要存儲的數據的指針。

getput通過引用獲取數據,因此不需要顯式地獲取指針。不幸的是,因爲這個模板只會涉及任何事情,所以沒有編譯器警告或錯誤來解決這個錯誤。

put,有兩種選擇:

75576​​

或執行相同,或與該實施例結構的一個替換表指針的表的示例結構的環。

struct EXAMPLE value_table[] = 
{ 
    { 
     { 
      {1, 8}, 
      {2, 9}, 
      {3, 10}, 
      {4, 11}, 
      {5, 12}, 
      {6, 13}, 
      {7, 14} 
     }, 
     {15, 16, 17} 
    }, 
    { 
     // contents of VALUE_2 
    }, 
    { 
     // contents of VALUE_3 
    }, 
    ... 
    { 
     // contents of VALUE_N 
    } 
} 

VALUE_1等等被丟棄。

相反要麼使用value_table[x]其中x是值號-1或定義

enum VALUES 
{ 
    VALUE_1 = 0, 
    VALUE_2, 
    VALUE_3, 
    ... 
    VALUE_N 
} 

和訪問表作爲value_table[VALUE_1]。這種方法有點冗長,但更容易閱讀。

put的調用仍然與當前使用的類似,只是丟失了操作員的地址。

EEPROM.put(0, value_table); 

使用get將是極其相似

EEPROM.get(0, VALUE_1); 
EEPROM.get(sizeof(VALUE_1), VALUE_2); 
EEPROM.get(sizeof(VALUE_1)*2, VALUE_3); 
... 
EEPROM.get(sizeof(VALUE_1)*(N-1), VALUE_N); 

EEPROM.get(0, value_table); 

取決於選擇處理put的方法。

+0

正如我告訴你的......沉浸在一個點,它更容易拍攝自己的腳(和這非常棒,因爲純粹的C/C++就像新人沒有安全網的高性能自殺工具:))。 unix'write(...)'至少會強制你指定大小,所以你必須知道你的內存結構是什麼樣的,在這裏你可以使用'&value_table',編譯器甚至不會對你眨眼。 :) – Ped7g