I'm using Rockwell Automation Connected Components Workshop (CCW).
I need to convert a REAL type to a byte array to be sent over RS-232/ASCII. How can this be achieved?
I'm using Rockwell Automation Connected Components Workshop (CCW).
I need to convert a REAL type to a byte array to be sent over RS-232/ASCII. How can this be achieved?
The simplest way is to use the COP instruction.
Copies the binary data in the source element to the destination element. The source element remains unchanged.
COP_1(Enable:=TRUE, Src:=3.14, SrcOffset:=0, Dest:=byte_array, DestOffset:=0, Length:=4, Swap:=FALSE);
The disadvantage is that you will need extra code to verify COP finished before proceeding.
Create a user-defined function, say REAL_TO_754_INT (all variables are DINT, except In_f32 and norm_f32, which are 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
Then mask and shift repeatedly to divide into bytes:
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));