A couple of years ago I wrote a tutorial about LSW MSW conversion to IEEE754 Float 32bit single precision

Now, I get the reverse need: starting from a given 32Bit Float calculate the LSW and MSW

This is normally made by storing the float into a %MD area (ex: %MD0) and by reading LSW at %MW0 and MSW at %MW1.

But I'm using a PLC development environment not equipped by Addressing area or Pointers: STRATON v.9.1

As knew, this is the structure of an IEEE754 32Bit Floating Point

and this is the rule to Convert -1313.3125 to IEEE 32-bit floating point format (thanks to Wikipdia)

A single-precision binary floating-point number is stored in a 32-bit word:

In this format the initial bit is not suppressed, and the radix point is set to the left of the mantissa in increments of 4 bits.

Since the base is 16, the exponent in this form is about twice as large as the equivalent in IEEE 754, in order to have similar exponent range in binary, 9 exponent bits would be required.

Example

Consider encoding the value −118.625 as an IBM single-precision floating-point value.

The value is negative, so the sign bit is 1.

The value 118.62510 in binary is 1110110.1012. This value is normalized by moving the radix point left four bits (one hexadecimal digit) at a time until the leftmost digit is zero, yielding 0.011101101012. The remaining rightmost digits are padded with zeros, yielding a 24-bit fraction of .0111 0110 1010 0000 0000 00002.

The normalized value moved the radix point two digits to the left, yielding a multiplier and exponent of 16+2. A bias of +64 is added to the exponent (+2), yielding +66, which is 100 00102.

Combining the sign, exponent plus bias, and normalized fraction produces this encoding:

On internet you can find many good website for online conversion such this

By translating that rule into IEC61131 ST language, this is the result:

These are the in/out function parameters:

VAR_INPUT
IN : REAL ;  // Floating point input value
END_VAR
VAR_OUTPUT
DW : DWORD ;
Exponent : STRING(8) ;
END_VAR
VAR
Sign : BOOL ;
Expon : DINT ;
IntegDec : DINT ;
i : DINT ;
BitTrue : BOOL ;
Fract : REAL ;
rest : REAL ;
e : DINT ;
id : DINT ;
FractBin : STRING(32) ;
IntegBin : STRING(32) ;
OneChar : STRING(1) ;
Flag : STRING(32) ;
Mantissa : STRING(23) ;
FlagD : DINT ;
END_VAR

And this is the code

//-----------------------------------------------------------
// reset DW each cycle
DW:=0;
//-----------------------------------------------------------
// void exponent normalization (e=0 or e=255)
if abs(IN)<0.0000001 then
DW:=0;
return;
end_if;

//-----------------------------------------------------------
// CALCULATE SIGN (- = Bit TRUE, +=Bit FALSE)
Sign:=IN<0;
//-----------------------------------------------------------
//  Integer part of REAL (base 10)
IntegDec:=any_to_dint(abs(IN));

// Convert Integer part of REAL to BIN
IntegBin:='';
FlagD:=IntegDec;

while FlagD>0 do
if FlagD-((FlagD/2)*2)=1 then
IntegBin:=INSERT(IntegBin,'1',1);
else
IntegBin:=INSERT(IntegBin,'0',1);
end_if;
FlagD:=FlagD/2;
end_while;

//-----------------------------------------------------------

// Convert Fractional part of REAL (base 10)
Fract:=abs(IN-trunc(IN));

// Convert Fractional part of REAL to BIN
FractBin:='';
rest:=Fract;
for i:=0 to 32 by 1 do
rest:=rest*2;
if rest>=1 then
FractBin:=concat(FractBin,'1');
rest:=rest-1;
else
FractBin:=concat(FractBin,'0');
end_if;
end_for;
//-----------------------------------------------------------// EXPONENT

e:=0;
rest:=Fract;

if IntegDec>=1 then             // if intergral part of IN is >1 =>
for i:=0 to 31 by 1 do
BitTrue:=testbit(IntegDec,i);
if BitTrue then
e:=i;
end_if;
end_for;
else
Flag:=FractBin;
for i:=0 to 31 by 1 do
OneChar:=LEFT( Flag,1 );
if OneChar='1' then
e:=-1*(i+1);
exit;
end_if;
Flag:=DELETE( Flag, 1,1);  // delete left chararcter
end_for;
end_if;

Expon:=e+127;

// convert Exponent to BIN
Exponent:='';
i:=7;
while i>=0 do
BitTrue:=testbit(Expon,i);
if BitTrue then
Exponent:=concat(Exponent,'1');
else
Exponent:=concat(Exponent,'0');
end_if;
i:=i-1;
end_while;
//-----------------------------------------------------------// MANTISSA
Mantissa:='';
if e=0 then
Mantissa:=FractBin;
elsif e>0 then
Mantissa:=CONCAT(RIGHT( IntegBin , e ),FractBin);
elsif e<0 then
Mantissa:=DELETE( FractBin, abs(e), 1 );
end_if;
//-----------------------------------------------------------
// Write DW
DW.31:=Sign;
DW.30:=Expon.7;
DW.29:=Expon.6;
DW.28:=Expon.5;
DW.27:=Expon.4;
DW.26:=Expon.3;
DW.25:=Expon.2;
DW.24:=Expon.1;
DW.23:=Expon.0;

Flag:=Mantissa;
i:=22;
while i>=0 do
BitTrue:=left(Flag,1)='1';
if BitTrue then
DW:=setbit(DW,i,true);
else
DW:=setbit(DW,i,false);
end_if;
Flag:=DELETE( Flag, 1,1);
i:=i-1;
end_while;

This is the function debugging:

I wish my notes can be helpful to someone