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

 Straton

 

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

 IEEE753 32Single Wiki

 

 

 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:

IBM1

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:

IBM2

 

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