Modbus/TCP Conversion between float & binary

Q

Thread Starter

Quim_Sabat

Hi, I need to convert a float to his binary representation (32 bits, intel float, in a "0" and "1" string). Anybody knows how to do it or where to find the algorithm ? Thank's for your help. Quim Sabat E-mail. [email protected]
 
K

Konrad Heidrich

Hi, when I understand you right, you've a REAL on the wire (MB/TCP)? It's already in binary form on the net and you can read it as two WORDs on the other side because there is no information about the type in the protocol. Perhapes you've to change the byte- or word order, I'm not absolutely sure in which order a 4 byte variable is on the wire.
 
If it's an IEEE 32 bits float, it's already in Intel 32 bits like format. The only thing you have to concern is that the store order of internal bytes in your hardware platform, somes are "least significant byte" first like Intel does and others are "most significant byte"first. Any data IS stored in binary in microprocessor. For Modbus protocol, it transfters one word with Hi-byte first, and in Modicon's PLC, uses two registers (4x) to represent one 32 bits IEEE data, LOW word first. In intel's CPU, one 32 bits foalt should stored like byte0, byte1, byte2, byte3. But if you look detail of Modbus protocol, the data should read like (reg 4x and 4x +1 represent 32 bits float): ....... ,4x (byte1, byte0), 4x+1 (byte3, byte2),.... If you work above of Modbus protocol ( there is a Modbus driver or something similar), since it's low word first, it's already at right format; but if you work with protocol itself, you only need to change the byte order of 4x and 4x+1. Let it at 0, 1, 2, 3 order. and you need to change the order to present word correctly as well if you read words. Hope above information helps.
 
J

Johan Bengtsson

Let's see if I understand your question correctly: You have a floating point number, stored in the way an intel processor stores a floating point value in 32 bits (what would in C mean the datatype short when compiled for an x86 processor) Are you doing this in a PC or in some other device? Are you doing it in C or some other language? If you are doing it in C, try this: union { float fVal; unsigned long iVal; } value; unsigned long i; char buffer[33],*p=buffer; value.fVal=1.11; //your floating point value goes here for (i=0x80000000;i;i>>=1) *p++=(value.iVal&i)?'1':'0'; *p=0; //buffer now contains the resulting string printf("result:\"%s\"\n",buffer); The above code uses the same memory location to store the value as a float and a unsigned long, these two types have the same size (32 bits) and will occupy the same memory The value are then checked once for each bit and the string built accordingly. The first char is the most significant bit (ie the sign bit of the floating point value), then follows the exponent and last the mantissa. If you would like the LSB first change the for statement like this: for (i=1;i;i<<=1) If you do it in some other language or device, first check if there is any possibility to store the float and access that pece of memory as if there was an integer stored and thereby use the same principle as above Johan Bengtsson ---------------------------------------- P&L, Innovation in training Box 252, S-281 23 H{ssleholm SWEDEN Tel: +46 451 49 460, Fax: +46 451 89 833 E-mail: [email protected] Internet: http://www.pol.se/ ----------------------------------------
 
C

Curt Jeffreys

Are you wanting to convert to a string of 1s and 0s? If not, the float is already binary. If you want it in another form, in C you can coerce it to an unsigned long. Curt
 
R

Robert Smyth

Depends on: 1. What programming language are you using 2. What processor are you used (not applicable if your using a PLC or similar) 3. What do want to talk to, you need to know how it implements floating point using Modbus. Robert Smyth EngWare Pty Ltd Voice: 0411 202 514 Fax: 02 9222 1457 E-mail: [email protected]
 
D

Darold Woodward

Floating point numbers in a Modicon PLC are stored using standard IEEE 32-bit floating point notation. The number is stored LSW, MSW in two 16-bit locations. You can convert with anything that can handle standard IEEE 32-bit floating point numbers once you arrange the words in the correct order (MSW, LSW). The word ordering is covered in an appendix of the Modbus TCP spec that you can get from Modicon. The IEEE 32-bit representation has been the standard for Modicon for a long time. Darold Woodward PE SEL Inc. [email protected]
 
Q
First, thank you for help , I give you more information : I use a string oriented language. It's 'M' language. I have a float. I don't know it's internal representation. I have to convert it to 4 bytes to send to a Modbus/TCP device. For example (it's not a real example): 3.45 is converted to 5 140 64 22 Where can I find the algorithm ? Quim Sabat E-mail. pr[email protected]
 
R

Rob Hulsebos

>For example (it's not a real example): >3.45 is converted to 5 140 64 22 What you must know is the binary format for a float on the destination processor. Most common now is the IEEE format, so I'll use that in my example below. A float is 32 bits long, and consists of 4 fields: a sign (+ -), a mantissa (digits), exponent, and sign of the exponent. IEEE assumes that all numbers are in the range 0..1, so the first thing we do is scale your number: 3.45 becomes 0.345 * 10^1. This is simple to code. We now know the sign (+), exponent (1) and sign of the exponent (+). Now convert the .345 to binary. This gives the mantissa. As the last step, join the 4 fields together in the way described by IEEE. The sign is + which becomes a zero bit. Same for the sign of the exponent. The exponent is 1, convert this to a 7-bit binary number. The mantissa is 23 bits. Together these are 32 bits, each of which has a fixed location. You are now ready with the conversion to IEEE format. It is slightly more complex than this, but I'd advise you to get a copy of the standard where all the small details are explained. Last comes the conversion of the 4 bytes to the format expected on the destination CPU. You may be forced to swap the MSW/LSW and/or the MSB/LSB per word. Rob Hulsebos
 
Hi, I am seeking for a C algorithm allowing conversion of a float to binary form (computing of the mantissa and exponent). Thanks for your help.
 
I need to convert a float to his binary representation (32 bits, intel float, in a "0" and "1" string). Anybody knows how to do it or
where to find the algorithm ?


#include <stdio.h>
#include <conio.h>

void main(){

// ****************************************************
// Purpose: Convert 4 bytes to an IEEE 4byte Float
// ****************************************************
// Accepts 4 bytes in keyboard and convets them to show
// as a IEEE FLOAT FORMAT (4 BYTE) value.
//
// by David, [email protected]

// ****************************************************

union { float fVal; unsigned char bytes[4]; } value;
int retval;
int i;
//Display Banner
printf(" **************************************************** \n");
printf(" Purpose: Convert 4 bytes to an IEEE 4byte Float \n");
printf(" **************************************************** \n");
printf(" RS232 Serial provides floats as 4 bytes. \n");
printf(" Demos to show how IEEE FLOAT FORMAT (4 BYTE) works \n");
printf(" <ctrl><c> to exit \n");
printf("\n by David, [email protected] \n");
printf("\n **************************************************** \n\n");

for(;;){
// Initalise Set to Zero
value.bytes[3] = 0;
value.bytes[2] = 0;
value.bytes[1] = 0;
value.bytes[0] = 0;

printf(" ** htof: 4 Bytes to Float Conversion.**\n");
printf(" Enter 4 Bytes to convert to IEEE float.\n");

for (i=0; i< 4 ; i++){

printf(" Enter Byte (as Hex) #%d = ", i);
retval = scanf( "%x", &value.bytes );
printf(" Byte %d Value = 0X%x \n", retval, value.bytes);

}
printf("\n IEEE FLOAT = %f \n", value.fVal );
printf(" IEEE 4 BYTE (Hex) = %2.2X %2.2X %2.2X %2.2X \n", value.bytes[3], value.bytes[2], value.bytes[1], value.bytes[0]);
printf(" ** htof: Conversion Done.** \n\n");

printf(" ** ftoh: Float to Hex Conversion.**\n");
printf(" Float value to convert to 4 Bytes = ");
retval = scanf( "%f", &value.fVal );
printf(" IEEE Format (Hex) = %2.2X %2.2X %2.2X %2.2X \n", value.bytes[3], value.bytes[2], value.bytes[1],
value.bytes[0]);
printf(" ** ftoh: Conversion Done.**\n\n");


}
}

 
G
> I need to convert a float to his binary representation (32 bits, intel
> float, in a "0" and "1" string). Anybody knows how to do it or where to
> find the algorithm ?

If I understand the question correctly, you have a float (4-byte IEEE format) and want to print out an ASCII string of 1's and 0's to
represent its bit pattern. If that's the case, just treat the float as a 4-byte buffer and mask off each bit in the byte, one at a time.

The example below prints the buffer left to right.


float f = -123.45;
unsigned char *p;
int i, j;

for (p = (unsigned char *)&f, i = 0; i < 4; p++, i++) {
for (j = 7; j >= 0; j--)
printf("%d", *p & (1 << j) ? 1 : 0);
printf(" ");
}
printf("\n");

You can verify that the bit masking works by substituting an arbitrary but recognizable 4-byte bit pattern for 'float f':

unsigned char f[4];

f[0] = (1 << 4) + 2;
f[1] = (3 << 4) + 4;
f[2] = (5 << 4) + 6;
f[3] = (7 << 4) + 8;

This produces the output bit pattern

00010010 00110100 01010110 01111000

which matches our expectations (a buffer of 8 consecutive nibbles loaded with the integers from 1 to 8).


Hope this helps,

Greg Goodman
Chiron Consulting

P.S. I have no idea what this has to do with Modbus/TCP.
 
Top