如何将指针数组中的值保存到EEPROM中的结构

时间:2016-08-11 17:01:13

标签: c++ arrays pointers avr

我正在尝试使用标准的Arduino EEPROM-Library Routine EEPROM.put()将4个结构中的所有值保存到我的ATMega328P EEPROM中,并通过EEPROM.get()检索它们。如何将value_table中的所有值传递给这些函数?这是我的数据的样子。

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 个答案:

答案 0 :(得分: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 ++? :/ *皱眉*

文档链接:getput,还有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]));
}

答案 1 :(得分: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,您有两种选择:

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

或执行相同操作的循环,或者用EXAMPLE结构的表替换EXAMPLE结构的指针表。

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的方法。