
Сообщение от
Евгений Кислов
Проблема воспроизвелась.
К сожалению, оперативно устранить ее не получится.
Насколько критична для вас невозможность записи значения этих параметров без дробной части?
Уточните, пожалуйста, какие параметры (кроме 'p.min') вынуждают вас использовать протокол ОВЕН вместо Modbus.
Для параметров P.min, P.max, P.nom, i.upr, i.min чтение можно осуществлять через формат с фиксированной точкой REAL_FRM.FIX_BIN, а вот запись необходимо осуществлять используя формат для целых чисел INT_FRM.UINT_FRM.
Структура формата REAL_FRM.FIX_BIN 16 битная:
0-11 - значение без точки.
12-14 бит - десятичный сдвиг точки
15 бит - знак, если 0 - то плюс, 1 - значит минуc
Примеры:
3.1=2#0001_0000_0001_1111
-3.1=2#1001_0000_0001_1111
0,300=2#0011_0001_0010_1100
Проблема крылась в том, что при записи целых положительных чисел биты 12-14 равны 0, тогда в битах 0-11 храниться целое значение. Но алгоритм работает с ошибкой, а при записи с десятичной точкой в битах 12-14 есть значения, т.е. все свелось к принудительной установке хотя бы одной точки после запятой.
Соответственно, для параметров P.min, P.max, P.nom, i.upr, i.min достаточно одной цифры после запятой, и необходимо знать знак числа.
Всем успехов 
Код проверен на ТРМ251 v1.10.
Мой пример реализации ниже.
Код:
GetReal:OWEN_GET_REAL;
SetDint:OWEN_SET_DINT;
i_min: // Огр. мин. интеграла
IF pribor^[prib_name].oper.StateTask[state].isRead THEN
GetReal(
Enable:= com_active,
Addr:= com_prib.addr[prib_name],
AddrLen:=com_prib.addrlen,
Name:='i.min' ,
Index:= 16#FFFF,
RealType:= REAL_FRM.FIX_BIN,
ComHandle:= hComTrm,
TimeOut:=com_prib.TimeOut*T#1MS ,
Complete=>,
Value=> ,
wTime=> ,
Error=> );
IF GetReal.Complete OR GetReal.Error<>0 THEN
pribor^[prib_name].oper.StateTask[state].error:=SetReal.Error;
CASE GetReal.Error OF
NoError:
pribor^[prib_name].pid.i_min:=GetReal.Value;
pribor^[prib_name].oper.StateTask[state].ValReal:=GetReal.Value;
state:=StateNoError(state:=state,StateTaskPt:=ADR(pribor^[prib_name].oper.StateTask));
NACK:
state:=end_pooling;
ELSE
state:=StateNoError(state:=state,StateTaskPt:=ADR(pribor^[prib_name].oper.StateTask));
END_CASE
GetReal(Enable:=FALSE);
END_IF
ELSE
IF pribor^[prib_name].pid.i_min >-0.001 THEN
SetDint.Value:=2#0001_0000_0000_0000; // Положительное число, одна цифра после запятой
ELSE
SetDint.Value:=2#1001_0000_0000_0000; // Отрицательное число, одна цифра после запятой
END_IF
SetDint(
Enable:= com_active,
Addr:= com_prib.addr[prib_name],
AddrLen:= com_prib.addrlen,
Name:= 'i.min',
Index:= 16#FFFF,
IntType:=INT_FRM.UINT_FRM,
Value:=REAL_TO_DINT(ABS(pribor^[prib_name].pid.i_min*10)) + SetDint.Value, // Сдвиг запятой на 1 знак в право.
ComHandle:= hComTrm,
TimeOut:= com_prib.TimeOut*T#1MS,
Complete=> ,
Error=> );
IF SetDint.Complete OR SetDint.Error<>0 THEN
pribor^[prib_name].oper.StateTask[state].error:=GetDint.Error;
CASE SetReal.Error OF
NoError:
state:=StateNoError(state:=state,StateTaskPt:=ADR(pribor^[prib_name].oper.StateTask));
NACK:
state:=end_pooling;
ELSE
state:=StateNoError(state:=state,StateTaskPt:=ADR(pribor^[prib_name].oper.StateTask));
END_CASE
SetDint(Enable:=FALSE);
END_IF
END_IF