Программирование ПЛК: преобразование в тип данных того же размера и обратное изменение фактического значения

Функциональный блок дает мне тип данных REAL. Реальное должно быть преобразовано в DWORD. На используемой платформе типы данных имеют следующие размеры:

  • РЕАЛЬНО: 32 бита (4 байта)
  • DWORD: 32 бита (4 байта)

Итак, я думаю, что если между этими двумя типами данных будет передано только битовое представление, значение не изменится или не потеряет точность. Я пытаюсь сделать следующее:

myReal : REAL;
myDWord : DWORD;
myResultReal : REAL;

myReal := 0.819;

myDWord := REAL_TO_DWORD(myReal);
myResultReal := DWORD_TO_REAL(myDWord);

// myResultReal has value: 1
// Also when I check the bit string of the myDWord it differs from the actual
// bit string of myReal. Immediately after the first conversion.

Вся проблема только в правилах языка программирования. Поскольку оба типа данных имеют одинаковый объем памяти, преобразование кажется совершенно ненужным. Фактическая причина для конвертации - просто потому, что мне нужно передать свой номер в код позже, который принимает только типы данных DWORD. Затем он использует DWORD, чтобы получить РЕАЛЬНОЕ, но в этот момент значение нежелательно.

3 ответа

Есть два варианта. Любитель, который предложил pboedker: тип данных UNION.

Пример:

TYPE U_TestUnion :
UNION
    Value_DWORD : DWORD;
    Value_REAL  : REAL;
END_UNION
END_TYPE   

VAR
    TestUnion   : U_TestUnion;
END_VAR

 TestUnion.Value_REAL := 0.819;
 //TestUnion.Value_DWORD is now 1062316540 (=16#3F51A9FC)

 TestUnion.Value_DWORD := 10; 
 //TestUnion.Value_REAL is now 1.401298E-44 

 TestUnion.Value_DWORD := 1062316540; 
 //TestUnion.Value_REAL is now 0.819 

Другая - использовать функцию MEMCPY, которая копирует значения из памяти в другое место. Функция может называться немного по-разному в разных системах. Делая это, вы можете скопировать содержимое из местоположения вашего реального значения на адрес DWORD и обратно.

В направлении REAL->DWORD не должно быть никаких забот. Но при копировании из DWORD в REAL могут возникнуть некоторые проблемы, если есть вероятность, что данные были изменены где-либо. Возможно, что значением будет NaN или Infinity, что может вызвать сбой ПЛК. Это означает, что РЕАЛЬНО не правильно отформатированный десятичный номер.

VAR
    Value_DWORD : DWORD;
    Value_REAL  : REAL;
END_VAR

Value_REAL := 0.819;
MEMCPY(destAddr:=ADR(Value_DWORD), srcAddr:=ADR(Value_REAL), n:=SIZEOF(Value_REAL));
 //Value_DWORD is now 1062316540 (=16#3F51A9FC)

Value_DWORD := 10; 
MEMCPY(destAddr:=ADR(Value_REAL), srcAddr:=ADR(Value_DWORD), n:=SIZEOF(Value_DWORD));
 //Value_REAL is now 1.401298E-44 

Value_DWORD := 1062316540; 
MEMCPY(destAddr:=ADR(Value_REAL), srcAddr:=ADR(Value_DWORD), n:=SIZEOF(Value_DWORD));
 //Value_REAL is now 0.819 

Проблема в том, что вы используете преобразование, поэтому ваш REAL=0,819 будет преобразован в DWORD=1 и обратно в REAL=1. Битовое представление будет изменяться соответственно при каждом преобразовании.

Решением вашей проблемы является использование UNION (IEC 61131-3). Таким образом, вы можете записать в часть REAL, передать часть DWORD в другой код, а затем снова использовать часть REAL в этом коде.

Простым решением было бы умножить реальное значение в 10 n раз перед преобразованием, в зависимости от требуемой точности, например:

myReal := 0.819;

myDWord := REAL_TO_DWORD(myReal * 1000);
myResultReal := DWORD_TO_REAL(myDWord)/1000;

Другие вопросы по тегам