Конвертировать Q18.2 в плавающее - PullRequest
0 голосов
/ 29 апреля 2018

Я пытаюсь прочитать значение давления из MPL3115 . В главе 14.3 DS говорит:

Данные о давлении хранятся в виде 20-разрядного целого числа без знака с дробной частью. OUT_P_MSB (01h), OUT_P_CSB (02h) и биты с 7 по 6 OUT_P_LSB (03h) регистры содержат целую часть в Паскалях. Биты с 5 по 4 из OUT_P_LSB содержат дробная составляющая. Это значение является репрезентативным для формата с фиксированной точкой Q18.2, где имеется 18 целочисленных битов и два дробных бита.

Вот мой (тестовый) код для Microchip XMEGA (GCC):

#define MPL3115_ADDRESS                 0x60
#define MPL3115_REG_PRESSURE_DATA       0x01

bool _ReadRegister(uint8_t address, uint8_t *readBuf, uint8_t readCount)
{
    TWI_MasterWriteRead(&twiMaster, MPL3115_ADDRESS, &address, 1, readCount);
    while (twiMaster.status != TWIM_STATUS_READY);
    memcpy(readBuf, (void *) twiMaster.readData, readCount);
    return true;
}

bool MPL3115_ReadPressure(float *value) {
    uint8_t raw[3];

    _ReadRegister(MPL3115_REG_PRESSURE_DATA, raw, 3);
    uint32_t data = (((uint32_t) raw[0]) << 16) | (((uint32_t) raw[1]) << 8) | raw[2];
    uint32_t q18n2 = data >> 4;

    *value = (double) q18n2 / 4;
    return true;
}

Я уверен, что линия i2c работает, потому что я могу успешно считывать температуру с того же чипа. Я настроил его в режиме барометра и 128 передискретизации (CTRL_REG1 = 0x38). В режиме отладки я прочитал следующие значения:

  • raw0 = 0x18
  • raw1 = 0x25
  • raw2 = 0x70
  • данные = 1582448

чтобы получить давление в Паскале, мне нужно сдвинуть данные вправо на 4 бита:

  • q18n2 = 98908

Теперь, чтобы преобразовать Q18.2 в число с плавающей точкой, я должен умножить на 2 ^ -n или разделить на 4:

  • значение = 24727 Па

Это должно быть в Паскале, так что разделите на 100 и получите мБар = 247,27 мБар ... вряд ли у меня здесь такое давление! Кстати сейчас должно быть около 1008 мБар.

Есть ли ошибки в моих мыслях?

1 Ответ

0 голосов
/ 08 июля 2018

Вы должны сдвинуть данные вправо на 6 битов, а затем добавить дробную часть (2 бита * 0,25).

*value = (raw0 << 10) | (raw1 << 2) | (raw2 >> 6);
*value += 0.25 * ((raw2 >> 4) & 0x03);
...