Код:
function_block FB_RealToWords_IEEE754
VAR_INPUT
InputReal : REAL;
END_VAR
VAR_OUTPUT
WordHigh : udint; // Старшие 16 бит (биты 31–16)
WordLow : udint; // Младшие 16 бит (биты 15–0)
StatusCode : udint; // 0: Normal, 1: Zero, 2: Infinity, 3: NaN
END_VAR
VAR
Sign : BOOL;
AbsValue : REAL;
Exponent : udint;
Mantissa : udint;
BiasedExp : udint;
SignBit : udint;
TempDword : udint;
i : udint;
buff_val : udint;
Fraction : REAL;
ScaledMant : REAL;
END_VAR
// ============================================================================
// ШАГ 1: Обработка особых случаев (до математических операций)
// ============================================================================
// Проверка на NaN (NaN != NaN по стандарту IEEE 754)
IF (InputReal <> InputReal) THEN
// NaN: Exponent = 255, Mantissa != 0
SignBit := 0;
BiasedExp := 255;
Mantissa := 4194304; // Quiet NaN
StatusCode := 3;
// Сборка UDINT
TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
WordHigh := shr(TempDword, 16) MOD 65536; // Старшие 16 бит
WordLow := TempDword MOD 65536; // Младшие 16 бит
RETURN;
END_IF;
// Проверка на бесконечность
IF (InputReal > 3.40282347E+38) OR (InputReal < -3.40282347E+38) THEN
// Infinity: Exponent = 255, Mantissa = 0
IF InputReal < 0.0 THEN
SignBit := 1;
ELSE
SignBit := 0;
END_IF;
BiasedExp := 255;
Mantissa := 0;
StatusCode := 2;
TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
WordHigh := shr(TempDword, 16) MOD 65536; // Старшие 16 бит
WordLow := TempDword MOD 65536; // Младшие 16 бит
RETURN;
END_IF;
// ============================================================================
// ШАГ 2: Извлечение знака
// ============================================================================
IF InputReal < 0.0 THEN
Sign := TRUE;
SignBit := 1;
AbsValue := -InputReal;
ELSIF InputReal > 0.0 THEN
Sign := FALSE;
SignBit := 0;
AbsValue := InputReal;
ELSE
// Случай нуля
Sign := FALSE;
SignBit := 0;
BiasedExp := 0;
Mantissa := 0;
StatusCode := 1;
TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
WordHigh := shr(TempDword, 16) MOD 65536; // Старшие 16 бит
WordLow := TempDword MOD 65536; // Младшие 16 бит
RETURN;
END_IF;
// ============================================================================
// ШАГ 3: Нормализация числа
// ============================================================================
Exponent := 0;
Fraction := AbsValue;
WHILE Fraction >= 2.0 DO
Fraction := Fraction * 0.5; // Деление на 2
Exponent := Exponent + 1;
END_WHILE;
WHILE Fraction < 1.0 DO
Fraction := Fraction * 2.0;
Exponent := Exponent - 1;
END_WHILE;
// ============================================================================
// ШАГ 4: Вычисление смещённой экспоненты (Bias = 127)
// ============================================================================
BiasedExp := Exponent + 127;
IF BiasedExp >= 255 THEN
// Переполнение -> Infinity
BiasedExp := 255;
Mantissa := 0;
StatusCode := 2;
TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
WordHigh := shr(TempDword, 16) MOD 65536; // Старшие 16 бит
WordLow := TempDword MOD 65536; // Младшие 16 бит
RETURN;
ELSIF BiasedExp <= 0 THEN
// Исчезновение -> Zero
BiasedExp := 0;
Mantissa := 0;
StatusCode := 1;
TempDword := shl(SignBit, 31) + shl(BiasedExp, 23) + Mantissa;
WordHigh := shr(TempDword, 16) MOD 65536; // Старшие 16 бит
WordLow := TempDword MOD 65536; // Младшие 16 бит
RETURN;
END_IF;
// ============================================================================
// ШАГ 5: Извлечение мантиссы (23 бита)
// ============================================================================
Fraction := Fraction - 1.0; // Убираем ведущую 1
ScaledMant := Fraction * 8388608.0; // 2^23 = 8388608
Mantissa := real_to_udint(ScaledMant + 0.5); // Округление
// Ограничиваем мантиссу 23 битами
Mantissa := Mantissa MOD 8388607;
// ============================================================================
// ШАГ 6: Сборка 32‑битного представления
// ============================================================================
TempDword := 0;
// Добавляем бит знака (бит 31)
IF SignBit = 1 THEN
TempDword := TempDword + 2147483648;
END_IF;
// Добавляем экспоненту (биты 30–23)
TempDword := TempDword + shl(BiasedExp, 23);
// Добавляем мантиссу (биты 22–0)
TempDword := TempDword + Mantissa;
// ============================================================================
// ШАГ 7: Разделение на два 16‑битных блока
// ============================================================================
buff_val := shr(TempDword, 16);
WordHigh := shr(TempDword, 16) MOD 65536; // Старшие 16 бит
WordLow := TempDword MOD 65536; // Младшие 16 бит
StatusCode := 0; // Normal
end_function_block