C ++ Объединение с плавающей запятой и проблема с байтовым массивом - PullRequest
0 голосов
/ 31 августа 2018

Я работаю на Arduino (на основе платформы AVR), и у меня есть метод, который принимает поплавок и записывает его в EEPROM. Я должен преобразовать float в байтовый массив для взаимодействия с 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 голосов
/ 01 сентября 2018

Arduino предоставляет методы .put () и .get () с объектом EEPROM, поэтому вам не нужно заново изобретать колесо. Ваш код может быть таким простым:

void WriteFloatToEEPROM(int address, float value)
{
    EEPROM.put(address, value);
}

float ReadFloatFromEEPROM(int address)
{
    float value;
    EEPROM.get(address, value);
    return value;
}

.put() также действует аналогично .update()

Эта функция использует EEPROM.update() для выполнения записи, поэтому не перезаписывает значение, если оно не изменилось.

0 голосов
/ 11 сентября 2018

Это общая проблема для структуры и объединения. Вам нужно исследовать "выравнивает". По умолчанию это обычно слово (2 байта), поэтому ваш byte byteVal[4]; может занять 8 байтов (byte, empty, byte, empty ...). Вы должны использовать __attribute__ ((packed)), чтобы избежать этого.

0 голосов
/ 31 августа 2018

Чтение не "активным" полем объединения - 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;
}
...