Как преобразовать REAL (32-разрядное число с плавающей запятой) в 8-разрядный байтовый массив в представлении IEEE 754?
Я использую Rockwell Automation по подключенным компонентам (CCW).
Мне нужно преобразовать тип REAL в байтовый массив для отправки через RS-232/ASCII. Как этого достичь?
2 ответа
Самый простой способ - использовать инструкцию COP.
Копирует двоичные данные в элементе источника в элемент назначения. Исходный элемент остается неизменным.
COP_1(Enable:=TRUE, Src:=3.14, SrcOffset:=0, Dest:=byte_array, DestOffset:=0, Length:=4, Swap:=FALSE);
Недостатком является то, что вам потребуется дополнительный код для проверки завершения COP перед продолжением.
Создайте пользовательскую функцию, скажем, REAL_TO_754_INT (все переменные - DINT, кроме In_f32 и norm_f32, которые являются REAL):
// Ref: http://beej.us/guide/bgnet/examples/pack2.c
IF In_f32 = 0.0 THEN
// get this special case out of the way
REAL_TO_754_INT := 0;
ELSE
// check sign and begin normalization
IF In_f32 < 0.0 THEN
sign := 1;
norm_f32 := -In_f32;
ELSE
sign := 0;
norm_f32 := In_f32;
END_IF;
// get the normalized form of f and track the exponent
shift := 0;
WHILE (norm_f32 >= 2.0) DO
norm_f32 := norm_f32 / 2.0;
shift := shift + 1;
END_WHILE;
WHILE (norm_f32 < 1.0) DO
norm_f32 := norm_f32 * 2.0;
shift := shift - 1;
END_WHILE;
norm_f32 := norm_f32 - 1.0;
// calculate the binary form (non-float) of the significand data
// 23 is the number of significand bits
significand := ANY_TO_DINT(norm_f32 * ANY_TO_REAL(SHL(1, 23)) + 0.5);
// get the biased exponent
// 7 is (number of exponent bits, 8)-1
expn := shift + (SHL(1,7) - 1); // shift + bias
// return the final answer
// 31 is (the total number of bits, 32)-1
REAL_TO_754_INT := OR_MASK(OR_MASK(SHL(sign, 31), SHL(expn, 23)), significand);
END_IF; // In_f32
Затем замаскируйте и сдвиньте несколько раз, чтобы разделить на байты:
as_DINT := REAL_TO_754_INT(your_REAL);
message[1] := ANY_TO_BYTE(AND_MASK(as_DINT, 16#FF));
message[2] := ANY_TO_BYTE(AND_MASK(SHR(as_DINT,8), 16#FF));
message[3] := ANY_TO_BYTE(AND_MASK(SHR(as_DINT,16), 16#FF));
message[4] := ANY_TO_BYTE(AND_MASK(SHR(as_DINT,24), 16#FF));