1

I have a modbus devices which saves 32-bit float values in IEEE754 format. In arduino, which uses C ofcourse, I can retrieve those values seperated into two 16-bit values, which are returned in uint16_t values. (each register from the modbus device has 16-bits, so the value is split over two registers, but the library I use returns uint16_t).

I am now trying to figure out to get these two uint16_t's into 1 32-bit float, and I would like to get some help, because I am stuck at how to convert this into this type of value.

Thanks in advance for your help.

EDIT:

To clarify, here's a format image IEEE754

the busybee
  • 10,755
  • 3
  • 13
  • 30
  • Generally, you'll want to avoid floating point like the plague on old 8 bitters. It's not a PC, there's no FPU. As for your question, you'll have to convert to `uint32_t` first, shift the words/bytes into the correct positions, then convert to `float` from there. Keep in mind both CPU and network endianess - CPU should be little endian in this case. – Lundin Jan 14 '20 at 08:29
  • 1
    The "standard" language for Arduino is actually C++, not C. If you build manually you can of course build plain C programs for it, but in the Arduino IDE the C++ compiler will be used (since all of the Arduino "standard" classes are just that: C++ classes). – Some programmer dude Jan 14 '20 at 08:33
  • Did you try a union of one `float f` and one `uint16_t r[2]`? – the busybee Jan 14 '20 at 08:36
  • @Lundin It depends on the requirements, as always. Arduinos are more powerful than the PC we had in the 80s. – the busybee Jan 14 '20 at 08:39
  • @thebusybee That could be bad... Unless the code is specifically C and built as C then type-punning through unions are not allowed (it leads to *undefined behavior* in C++). – Some programmer dude Jan 14 '20 at 08:39
  • Well, my C++ experience is limited, sorry. There should be a similar way, though. I'm just making proposals for further research. – the busybee Jan 14 '20 at 08:48
  • @thebusybee No it isn't. 80286 was 16 bit and had floating point support. And Motorola 68k was faster yet. – Lundin Jan 14 '20 at 10:24
  • @Lundin Let's talk about affordable PCs of the 80s: CP/M and XTs. And I'm sure that a 12 MHz 286 (without floating point coprocessor) is slower than a 16 MHz AVR when doing floating point calculations. I got my first 286 at the job around 1990, but my 85's Atari ST was faster. Whether it was faster than a modern AVR, I don't know. Do you have firm numbers like whetstone results? – the busybee Jan 14 '20 at 14:12

1 Answers1

1

The only way around strict aliasing or invalid type-punning is really through the use of std::memcpy:

uint16_t const value[2] = { low_word, high_word };  // Assuming little-endianness
float f;

std::memcpy(reinterpret_cast<void*>(&f), reinterpret_cast<void const*>(value), sizeof f);
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Or use `-fno-strict-aliasing` compiler option, if the performance impact is negligible. – Tagli Jan 14 '20 at 12:28