Как преобразовать четыре uint16_t в двойное число с плавающей запятой IEEE754?

Я работаю над проектом Modbus, где мне нужно считывать регистры хранения и ввода Modbus с помощью ESP8266, я использую библиотеку ModbusMaster232. Я возвращаю массив буфера ответа uint16_t. Мне нужно преобразовать uint16_t в число с плавающей запятой двойной точности. Быстрый тест в ESP8266 показывает, что двойной тип данных в ESP8266 хранит 8 байтов. Кто-нибудь знает, как преобразовать четыре uint16_t в double в Arduino. Если да, поделитесь своими знаниями.

, 👍0


1 ответ


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

0

Вот фрагмент кода для преобразования uint16_t. Разверните это, чтобы работать с вашим массивом целых чисел из библиотеки. Помните, что на Arduino, Uno и Mega, по крайней мере, двойные числа реализованы как числа с плавающей запятой. Вы не получите той точности, на которую рассчитывали.

double xAsDouble;    // ** только точность с плавающей запятой, несмотря на объявление 'double'
uint16_t xAsInt;

xDouble = xInt;      // компилятор знает, как сделать это преобразование.

Обновление: перечитав ваш вопрос, я понял, что вы используете ESP8266. Мои комментарии о точности с плавающей запятой Uno могут быть неприменимы.

Обновление 2. После некоторого обсуждения я узнал, что Modbus возвращает не 4 целых числа, а двойное число, которое передается как 4 слова, которые необходимо собрать заново, чтобы воссоздать исходное двойное число. Решение будет зависеть от порядка, в котором отправляются слова, составляющие исходный дубль.

Обновление 3: я предложил ОП попробовать использовать эту общую схему:

// Объединение позволяет вам рассматривать память как (в данном случае) 4 целых числа или 1 двойное число
union {
   uint16_t data_out[4];
   double x;
} buffer;

// Назначить данные из Modbus, используя способ просмотра памяти 'int'.
// Обратите внимание, что я могу ошибаться в порядке, но идея такова:
buffer.data_out[i] = data_in[i];

Тогда чтение 'buffer.x' приведет к получению 4 слов памяти как двойного.

... Попробовав оба порядка, ОП сообщает, что он получил ожидаемый результат,

,

Спасибо за ответ @JRobert, но я использую массив **uint16_t** с 4 элементами, а не одну переменную uint16_t, мне нужно сгруппировать эти _четыре 16-битных контейнера в один 64-битный контейнер_, представляющий **переменную с плавающей запятой IEEE754**. Не могли бы вы уточнить, как код будет делать это, @Mr.B

Вы понимаете, как использовать цикл for() для выполнения одного или нескольких операторов над членами (элементами) в массиве?, @JRobert

Ты имеешь ввиду uint16_t data_in={2121,1233,3435,2433}; двойной data_out=0; для (целое я = 0; я <4; я ++) { данные_выход = данные_выход | data_in[i]<<16; }, @Mr.B

Да - пожалуйста, смотрите мой отредактированный комментарий выше. Вы бы сделали то же самое, что и в моем примере, но использовали [i] для адресации каждого из целых чисел и чисел с плавающей запятой., @JRobert

Это правильный код @JRobert?, @Mr.B

Выньте левую смену - все, что вам нужно, это простое задание. Компилятор знает из ваших объявлений, что «data_out» — это double, а «data_in» — это uint_16, и как присвоить одно другому, включая правильное преобразование., @JRobert

Попробую, как вы сказали, на моей плате ESP8266 и вернемся обратно @JRobert, @Mr.B

Как я и ожидал, я получаю значение последнего элемента в массиве с десятичным числом @JRobert, @Mr.B

Давайте [продолжим это обсуждение в чате](https://chat.stackexchange.com/rooms/107093/discussion-between-mr-b-and-jrobert)., @Mr.B