Преобразование 16 бит в число с плавающей запятой

Я пытаюсь связаться с AT30TS75A-MA8M-T с помощью приведенного ниже кода, проблема заключается в преобразовании 16-битного вывода в число с плавающей запятой, чтобы я мог читать temp:

На основе паспорта Я предполагаю удалить первые 5 бит, чтобы правильно читать, но я не конвертирую их правильно.

Пример: (0b001001001100000 И 0 b0111111111100000) = 0b1001001100000 0b1001001100000 >> 5 = 0b10010011 = 147

    void Atemp::begin()
{

    Wire.begin();

    // Проверяем, доступен ли датчик температуры датчика

    // если (mySensor.beginI2C() == false)
    // {
    // данные[9] = 5; // Код ошибки
    // }
    // Установить регистр для двух десятичных знаков
    Wire.beginTransmission(_i2cAddress);
    Wire.write(1);
    Wire.write(0b01100000);
    Wire.endTransmission();
}

void Atemp::read()
{
    Wire.beginTransmission(_i2cAddress);
    Wire.write(0);
    result = Wire.endTransmission();
    // результат 0-4
    if (result != 0)
    {
        data[9] = 5; // Код ошибки
    }

    result = Wire.requestFrom(_i2cAddress, (uint8_t)2);
    if (result != 2)
    {
        data[9] = 5; // Код ошибки
    }
    else
    {
        uint8_t part1 = Wire.read();
        uint8_t part2 = Wire.read();
        
        data[7] = part1;
         data[8] = part2;
        int16_t rawval = (part1 << 8 | part2) ;
        // исходное значение >>= 6;
        float temp = rawval / 256.0f;
        floatconv(temp);
    }
}

, 👍1


2 ответа


Лучший ответ:

3

Вам нужно сделать две вещи:

  1. Сдвиньте данные вправо, чтобы выровнять их справа от переменной, и
  2. Умножьте его на значение одного бита.

При смещении вправо обязательно делайте это в типе данных signed, чтобы C знаковое расширение значения сохраняло отрицательные значения.

Итак, взяв 12-битные примеры из таблицы, вы сдвинете вправо 4 бита, так что

SDDDDDDDDDDD0000

становится

SSSSSDDDDDDDDDDD

(где S — знаковый бит, D — допустимый бит данных, а 0 — заполнение)

Затем просто умножьте значение на 0,0625, чтобы получить реальную температуру.

В коде, который может выглядеть так:

int16_t rawval = part1 << 8 | part2;
rawval >>= 4; // Сделайте это в int16_t, чтобы сохранить знак
float temperature = rawval * 0.0625;

Для разных разрешений сдвиньте вправо на разную величину и умножьте на соответствующее однобитное значение для этого разрешения (подсказка: 11 бит удваивает значение 12 бит, 10 бит удваивает значение 11 бит и т. д.).

,

@Shahreza Страница 10 таблицы данных. Разрешение данных измерения температуры может быть настроено на 9, 10, 11 или 12 бит, что соответствует приращения температуры 0,5°С, 0,25°С, 0,125°С и 0,0625°С соответственно. , @Majenko


3

Просто дополнение к ответу Маженко. Регистр температуры установлен таким образом, чтобы вы могли интерпретировать его одинаково независимо от выбранное разрешение:

int16_t rawval = part1 << 8 | part2;
float temperature = rawval * (1/256.0);
,

Хороший план - не подумал об этом ;), @Majenko