Как преобразовать четыре uint16_t в двойное число с плавающей запятой IEEE754?
Я работаю над проектом Modbus, где мне нужно считывать регистры хранения и ввода Modbus с помощью ESP8266, я использую библиотеку ModbusMaster232. Я возвращаю массив буфера ответа uint16_t. Мне нужно преобразовать uint16_t в число с плавающей запятой двойной точности. Быстрый тест в ESP8266 показывает, что двойной тип данных в ESP8266 хранит 8 байтов. Кто-нибудь знает, как преобразовать четыре uint16_t в double в Arduino. Если да, поделитесь своими знаниями.
@Mr.B, 👍0
1 ответ
Лучший ответ:
Вот фрагмент кода для преобразования 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 слов памяти как двойного.
... Попробовав оба порядка, ОП сообщает, что он получил ожидаемый результат,
- Печать unsigned long long в ESP8266
- Изменить строку типа данных
- Может быть, странная проблема, с которой я столкнулся, связана со сравнением чисел с плавающей точкой?
- Как читать и записывать EEPROM в ESP8266
- Как сделать выводы Tx и Rx на ESP-8266-01 в выводах GPIO?
- Как навсегда изменить скорость передачи данных ESP8266 (12e)?
- Float печатается только 2 десятичных знака после запятой
- Как заставить 5-вольтовое реле работать с NodeMCU
Спасибо за ответ @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