Преобразование двух переменных word в real.

Avatar
  • обновлен

Добрый день. Опрашиваю средствами modbus  driver СПК110 от Овен. СПК110 передает переменную real в виде двух переменных типа word. Как с помощью скрипта склеить обратно 2word_to_real? На паскале или си++. Simplite 4.7

Avatar

День добрый.


Уточните, устройство передает именно в двух регистрах число в формате real, или преобразовывает его в целочисленное значение и передает как word?

Avatar
евгений ситников

Image 2193

как 2 регистра

Image 2194

теперь нужно "склеить" два word в real

Avatar
{Pascal Script}
Var 
  singleValue: Double;   
  wHighWord    : Word;
  wLowWord     : Word;                   
                                              
 
function ConvertNumberToFloat(number: Int64; isDoublePrecision: Boolean): Double;
var
  mantissaShift: Integer;
  exponentMask: Int64;        
  bias: Integer;
  signShift: Integer;
  sign: Boolean;                                    
  exponent: Integer;
  power1: Integer;
  total: Double;
  i: Integer;
  calc: Integer;
  value: Double;
begin
  if isDoublePrecision then
  begin
    mantissaShift := 52;
    exponentMask := $7FF0000000000000;
    bias := 1023;                                                                
    signShift := 63;
  end                                                      
  else                                                                 
  begin
    mantissaShift := 23;
    exponentMask := $7F800000;
    bias := 127;
    signShift := 31;
  end;

  sign := not(((number shr signShift) and $01) = 1);
  exponent := ((number and exponentMask) shr mantissaShift) - bias;

  power1 := -1;
  total := 0.0;
  for i := 0 to mantissaShift - 1 do
  begin
    calc := (number shr (mantissaShift - i - 1)) and $01;
    total := total + calc * Power(2.0, power1);          
    power1 := power1 - 1;       
  end;
  total := total + 1.0;
                       
  if sign then                                                                                                                 
    value := 1 * Power(2.0, exponent) * total  
  else
    value := -1 * Power(2.0, exponent) * total;  
  Result := value;                                
end;        

function GetSinglePrecision(number: Cardinal): Single;
begin
  Result := ConvertNumberToFloat(number, False);
end;

function GetDoublePrecision(number: Int64): Double;
begin
  Result := ConvertNumberToFloat(number, True);
end;

                                                   
Begin    
  wHighWord := 16758;
  wLowWord := 26214;

  singleValue := GetSinglePrecision((wHighWord shl 16) or wLowWord);
                                                      
  WriteValue('Virtual channel', singleValue);  
end.          
Avatar
евгений ситников
Цитата от СИМП Лайт (тех поддержка)
{Pascal Script}
Var 
  singleValue: Double;   
  wHighWord    : Word;
  wLowWord     : Word;                   
                                              
 
function ConvertNumberToFloat(number: Int64; isDoublePrecision: Boolean): Double;
var
  mantissaShift: Integer;
  exponentMask: Int64;        
  bias: Integer;
  signShift: Integer;
  sign: Boolean;                                    
  exponent: Integer;
  power1: Integer;
  total: Double;
  i: Integer;
  calc: Integer;
  value: Double;
begin
  if isDoublePrecision then
  begin
    mantissaShift := 52;
    exponentMask := $7FF0000000000000;
    bias := 1023;                                                                
    signShift := 63;
  end                                                      
  else                                                                 
  begin
    mantissaShift := 23;
    exponentMask := $7F800000;
    bias := 127;
    signShift := 31;
  end;

  sign := not(((number shr signShift) and $01) = 1);
  exponent := ((number and exponentMask) shr mantissaShift) - bias;

  power1 := -1;
  total := 0.0;
  for i := 0 to mantissaShift - 1 do
  begin
    calc := (number shr (mantissaShift - i - 1)) and $01;
    total := total + calc * Power(2.0, power1);          
    power1 := power1 - 1;       
  end;
  total := total + 1.0;
                       
  if sign then                                                                                                                 
    value := 1 * Power(2.0, exponent) * total  
  else
    value := -1 * Power(2.0, exponent) * total;  
  Result := value;                                
end;        

function GetSinglePrecision(number: Cardinal): Single;
begin
  Result := ConvertNumberToFloat(number, False);
end;

function GetDoublePrecision(number: Int64): Double;
begin
  Result := ConvertNumberToFloat(number, True);
end;

                                                   
Begin    
  wHighWord := 16758;
  wLowWord := 26214;

  singleValue := GetSinglePrecision((wHighWord shl 16) or wLowWord);
                                                      
  WriteValue('Virtual channel', singleValue);  
end.          

Огромное спасибо за ответ. Завтра попробую:)