modbus_set_float() / modbus_get_float() in format ABCD

1,233 views
Skip to first unread message

Mads Lind Christiansen

unread,
Mar 31, 2014, 6:06:46 AM3/31/14
to libm...@googlegroups.com
I guess this is a topic everyone is tired of being debated, but still here it goes...

My understanding of the ABCD 32 bit byte ordering is this (this might be where I am getting it wrong?!?)
I have a 32 bit value (float), lets say it is presented in 32 bit as 0xAABBCCDD 
If it is sent in the ABCD format the byte order sent (on the network) should be 0xAA 0xBB 0xCC 0xDD, is this correct?

Because when I debug my code I can see that in a response, e.g.
            for (i = address; i < address + nb; i++) {
                rsp[rsp_length++] = mb_mapping->tab_registers[i] >> 8;
                rsp[rsp_length++] = mb_mapping->tab_registers[i] & 0xFF;
the libmodbus stack sends every 16 bit register with MSB first and the LSB (big endian byte order), which is just fine.

But with modbus_set_float() 
    memcpy(&i, &f, sizeof(uint32_t));
    dest[0] = (uint16_t)i;
    dest[1] = (uint16_t)(i >> 16);
dest[0] will hold 0xCCDD   
dest[1] will hold 0xAABB

when this is sent on the network the byte order will then be 0xCC 0xDD 0xAA 0xBB
I would have thought that it should have been 0xAA 0xBB 0xCC 0xDD ?

To have this I would have to change the modbus_set_float() to
    memcpy(&i, &f, sizeof(uint32_t));
    dest[0] = (uint16_t)(i >> 16);
    dest[1] = (uint16_t)i;

Why is libmodbus sending in format CDAB ? or am I missing something?

Many thanks in advance,
Mads




Chuck Watson

unread,
Mar 31, 2014, 7:04:03 AM3/31/14
to libm...@googlegroups.com

Its not libmodbus, it’s the slave device. Another type of slave device may send 32 bit values differently.

 

There are many variations in the MODBUS protocol.

 

 

Chuck Watson BS, CEM, CMVP
Direct USA 724-799-1529
www.EnergyChaser.com


--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "libmodbus".
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse libmodbus+...@googlegroups.com.
Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.

Mads Lind Christiansen

unread,
Mar 31, 2014, 7:47:32 AM3/31/14
to libm...@googlegroups.com
Hi Chuck

Thanks for you reply.

I am aware of the many different implementations of modbus.

I am just wondering why libmodbus defines the ABCD format as CDAB when transmitted on the network?

Since 16 bit registers are transmitted in the format AB, eg. 0xAABB is sent as 0xAA 0xBB (big endian),
I would assume that 32bits are transmitted in the form ABCD, eg. 0xAABBCCDD is sent as 0xAA 0xBB 0xCC 0xDD which is not the case?


Thanks,
Mads

Stéphane Raimbault

unread,
Apr 1, 2014, 10:43:07 AM4/1/14
to libm...@googlegroups.com
Hi Mads,

 

My understanding of the ABCD 32 bit byte ordering is this (this might be where I am getting it wrong?!?)

I have a 32 bit value (float), lets say it is presented in 32 bit as 0xAABBCCDD 

If it is sent in the ABCD format the byte order sent (on the network) should be 0xAA 0xBB 0xCC 0xDD, is this correct?


No, the data are swapped for the network transfer by set_float() and swapped again by modbus_get_float() on the other side (or other client code).
As said the Modbus spec isn't clear on the subject and various implementations exist, I think it's the most common way to fetch floats from the network.


Mads Lind Christiansen

unread,
Apr 1, 2014, 10:53:30 AM4/1/14
to libm...@googlegroups.com
Hi Stephane

Many thanks for you answer. I do get that set_float() is used for transmission and get_float() vice versa - and that libmodbus will work with this specific impl. if used on both sides, or any other impl. that formats floats in the same way.

What I find a bit difficult to understand is the comments in source code - modbus-data.c
/* Set a float to 4 bytes in Modbus format (ABCD) */
void modbus_set_float(float f, uint16_t *dest)
{
    uint32_t i;

    memcpy(&i, &f, sizeof(uint32_t));
    dest[0] = (uint16_t)i;
    dest[1] = (uint16_t)(i >> 16);
}

It states that modbus_set_float() uses the format ABCD. I would say that it does not. If the note 'ABCD' does not refer to the network byte order, then what does it refer to? It should have stated that the format used is CDAB.

I know that there are many different implementations of modbus and also of different ways to present 32 bit data.

Best wishes,
Mads

Mads Lind Christiansen

unread,
Apr 9, 2014, 2:32:37 AM4/9/14
to libm...@googlegroups.com
Hi Stephane

Could you comment on the modbus format ABCD is indeed the order the bytes are transferred on the network?

Please see below.

Stéphane Raimbault

unread,
Apr 9, 2014, 6:52:07 AM4/9/14
to libm...@googlegroups.com
Yes the comment in code could be improved, I don't know how to improve it. Could you propose something?

ABCD means the common Modbus format (CDAB on network)
DCBA means inversed Modbus format (BADC on network)


Mads Lind Christiansen

unread,
Apr 9, 2014, 7:22:38 AM4/9/14
to libm...@googlegroups.com
Hi Stephane

Many thanks again for your reply. I am truly sorry if I am bothering you too much, but before I can understand this definition, I need to understand where the term ABCD has been defined as the common Modbus format (CDAB on the network)?

There exists many different modbus implementations (properly as many as there are companies :-), but why go against the definition that modbus was designed as a big-endian protocol (all 16 bit registers are transmitted as as big endian). 

Now it may be hard to come up with old evidence that the definition ABCD is infact the network byte order but it seems logic to do so - and others also suggest this like http://www.chipkin.com/how-real-floating-point-and-32-bit-data-is-encoded-in-modbus-rtu-messages/ or the tool Modbus Poll (from www.modbustools.com - nothing to do with me, just using their tool).

The Modbus Application Protocol Specification, V1.1.b (http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1a.pdf) also specifies in section 4.2  the following:
MODBUS uses a ‘big-Endian’ representation for addresses and data items. This means 
that when a numerical quantity larger than a single byte is transmitted, the most 
significant byte is sent first.

Why not just decide that libmodbus uses the definition ABCD as the network byte order ABCD of a float or any other 32 bit value? 
Perhaps we need a rewrite of modbus-data.c to support (network byte order) ABCD, CDAB etc. and also APIs for 32 integers, and 64 bit data?

Best wishes,
Mads

Stéphane Raimbault

unread,
Apr 9, 2014, 8:04:30 AM4/9/14
to libm...@googlegroups.com
It seems logical to call the function according the applied conversion.

I didn't want to change the behavior of modbus_set/get_float in v3.1.x because the function already exists in stable branch. Calling the function get_float_dcba by supposing the existing one was abcd was a mistake, this error has been introduced in unstable release only so we can fix it.

I propose to keep modbus_set/get_float as it is but to change the behavior of mobdbus_set/get_float_dcba to (byte and word swap) :

float modbus_get_float_dcba(const uint16_t *src)
{
    float f;
    uint32_t i;

    i = bswap_32((((uint32_t)src[0]) << 16) + src[1]);
    memcpy(&f, &i, sizeof(float));

    return f;
}

and to create the missing functions (that why I added this suffix) modbus_set/get_float_abcd (nop), modbus_get_float_badc (byte swap), modbus_get_float_cdab (word swap).

The chipkin article is great and I'll write unit tests against the provided examples.

Stéphane Raimbault

unread,
Apr 14, 2014, 3:46:58 PM4/14/14
to libm...@googlegroups.com

Mads Lind Christiansen

unread,
Apr 23, 2014, 5:48:50 AM4/23/14
to libm...@googlegroups.com
Hi Stephane

So sorry for the late reply, was busy at work and on vacation.

I have just done a very quick review of your changes, I haven't tried them yet - will do sometime in the future when I get back to working on our modbus interface - could be a while though.

Perhaps you should also add to the comments of the deprecated functions what format (CDAB) they actually use.

But it looks great :-)

I was also wondering whether it would be nice to have the same conversion functions for 32 bit integers (signed and unsigned)? What do you think of this?

Best wishes,
Mads
Reply all
Reply to author
Forward
0 new messages