浮点数和字节数组问题的C ++联合

时间:2018-08-31 20:31:15

标签: c++ avr unions

我正在使用arduino(基于AVR平台),并且有一种方法可以接受一个浮点并将其写入EEPROM。我必须将浮点数转换为字节数组才能与EEPROM交互。我有两个功能,如下所示:

void WriteFloatToEEPROM(int address, float value) {
    union {
        byte byteVal[4];
        float floatVal;
    } data;

    data.floatVal = value;

    for (int i = 0; i < 4; i++) {
        EEPROM.update(address + i, data.byteVal[i]);
    }   
}

float ReadFloatFromEEPROM(int address) {
    union {
        byte byteVal[4];
        float floatVal;
    } data;

    for (int i = 0; i < 4; i++) {
        uint8_t readValue = EEPROM.read(address + i);

        data.byteVal[i] = readValue;        
    }

    return data.floatVal;
}

当我打印出结果时,我将获得以下示例:

Read value at address 50 for float read 0
Read value at address 51 for float read 0
Read value at address 52 for float read 0
Read value at address 53 for float read 0
    Returned float val for address 50:0.00
Read value at address 90 for float read 0
Read value at address 91 for float read 0
Read value at address 92 for float read 0
Read value at address 93 for float read 160
    Returned float val for address 90:-0.00
Read value at address 130 for float read 44
Read value at address 131 for float read 113
Read value at address 132 for float read 61
Read value at address 133 for float read 138
    Returned float val for address 130:-0.00
Read value at address 170 for float read 0
Read value at address 171 for float read 0
Read value at address 172 for float read 0
Read value at address 173 for float read 0
    Returned float val for address 170:0.00

我使用工会错误/向后写入EEPROM是什么吗?另外,如果有人有更好的方法可以这样做,我也乐于提出建议。预先感谢

3 个答案:

答案 0 :(得分:7)

未读并集的“活动”字段是UB(未定义行为)。

您必须使用memcpy

void WriteFloatToEEPROM(int address, float value) {
    byte byteVal[sizeof(float)];
    memcpy(byteVal, &value, sizeof(float));

    for (int i = 0; i < sizeof(float); i++) {
        EEPROM.update(address + i, byteVal[i]);
    }   
}

float ReadFloatFromEEPROM(int address) {
    byte byteVal[sizeof(float)];

    for (int i = 0; i < sizeof(float); i++) {
        byteVal[i] = EEPROM.read(address + i);
    }

    float f;
    memcpy(&f, byteVal, sizeof(float));
    return f;
}

答案 1 :(得分:3)

Arduino为each对象提供了.put().get()方法,因此您无需重新发明轮子。您的代码可能很简单:

$('li').each(function() {

});

EEPROM的行为也类似于void WriteFloatToEEPROM(int address, float value) { EEPROM.put(address, value); } float ReadFloatFromEEPROM(int address) { float value; EEPROM.get(address, value); return value; }

  

此函数使用.put()执行写操作,因此不执行   如果值不变,则将其重写。

答案 2 :(得分:0)

这是结构和联合的常见问题。您需要调查“对齐”。默认情况下,通常为“字”(2个字节),因此您的byte byteVal[4];可以占用8个字节(byte, empty, byte, empty ...)。您必须使用__attribute__ ((packed))来避免它。