2016-08-11 64 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