
Сообщение от
Ctakah133
Всем Доброго времени суток.
Столкнулся с такой бедой как "Числа в формате PIC с плавающей запятой" при опросе по RS485 счетчика газа Ирвис К-300.
ИрвисК300.png
Прошу вашей помощи, может кто то сталкивался с такой проблемой ранее, как эти значения привести к понятным REAL?
Вот функция на ST, можете проверить её с примером из документа. У меня результаты совпали.
Можно упростить, если использовать объединение (UNION).
Код:
FUNCTION PIC_TO_REAL : REAL
VAR_INPUT
picData : ARRAY[0..2] OF BYTE; // Три байта в формате PIC: [мл.байт мантиссы, ст.байт мантиссы, порядок]
END_VAR
VAR
abyTemp : ARRAY[0..3] OF BYTE; // 4 байта
dwTemp : DWORD;
result : REAL;
END_VAR
Код:
abyTemp[0] := 0; //Нулевой байт REAL = 0
abyTemp[1] := picData[0]; // Первый байт REAL = нулевой байт PIC (мл. байт мантиссы)
abyTemp[2] := picData[1] AND 16#7F; // Второй байт REAL = первый байт PIC (ст. байт мантиссы) со сброшенным знаком
// Проверка младшего бита порядка (из второго байта PIC)
IF (picData[2] AND 16#01) <> 0 THEN
// Если младший бит установлен, устанавливаем старший бит второго байта REAL
abyTemp[2] := abyTemp[2] OR 16#80;
END_IF
// Третий байт REAL = второй байт PIC, сдвинутый вправо на 1 бит
abyTemp[3] := SHR(picData[2], 1);
// Установка знакового бита в третьем байте REAL
IF (picData[1] AND 16#80) <> 0 THEN
// Если знак отрицательный (старший бит первого байта PIC установлен)
abyTemp[3] := abyTemp[3] OR 16#80;
ELSE
abyTemp[3] := abyTemp[3] AND 16#7F;
END_IF
// Копируем байты в DWORD
dwTemp := SHL(TO_DWORD(abyTemp[1]), 8) OR
SHL(TO_DWORD(abyTemp[2]), 16) OR
SHL(TO_DWORD(abyTemp[3]), 24);
// Копируем DWORD в REAL через указатель
MEM.MemMove(ADR(dwTemp), ADR(result), SIZEOF(result));
PIC_TO_REAL := result;