1

I'm trying to combine four 16 bit UINT to a single 64 bit UINT in codesys. I am able to do this in C but I haven't been able to figure out the syntax in Codesys. I have four elements of an array that are 16 bit UINT values.

If anyone knows a way to combine these please let me know. Thanks a lot.

VAR
     // Array
     UTCdataArray : ARRAY [0..3] OF UINT;     

     //16 bit UINT elements
     UTCval0: UINT := 0;
     UTCval1: UINT := 0;
     UTCval2: UINT := 0;
     UTCval3: UINT := 0;

     // 64 bit ULINT
     UTCval: ULINT := 0;
END_VAR


// 16 bit UINT array
UTCval0 := UTCdataArray[0];
UTCval1 := UTCdataArray[1];
UTCval2 := UTCdataArray[2];
UTCval3 := UTCdataArray[3];

// Combine 16 bit UINT array elements into 64 bit ULINT

//This is something I would do in C
UTCval := UTCval0 << 0;
UTCval := UTCval1  << 16;
UTCval := UTCval2  << 32;
UTCval := UTCval3  << 48;
Andrew180
  • 13
  • 2

2 Answers2

2

There are several ways to combine/divide data types into larger/smaller type.

One, as mentioned by kolyur, is using shift operators:

UTCval := UINT_TO_ULINT(UTCval0) + SHL(UINT_TO_ULINT(UTCval1), 16) + SHL(UINT_TO_ULINT(UTCval2), 32) + SHL(UINT_TO_ULINT(UTCval3), 48);

Though personally I never use that one.

Alternatively, you may use an array and pointer to "cast" the array into a larger type:

(*
_arr: ARRAY [0..3] OF UINT;
_p_ulint: POINTER TO ULINT;
*)

_arr[0] := UTCval0;
_arr[1] := UTCval1;
_arr[2] := UTCval2;
_arr[3] := UTCval3;

_p_ulint := ADR(_arr);

UTCval := _p_ulint^;

Or cast the larger type value into a small type array instead:

(* _p_uint: POINTER TO UINT; *)

_p_uint := ADR(UTCval);

_p_uint[0] := UTCval0;
_p_uint[1] := UTCval1;
_p_uint[2] := UTCval2;
_p_uint[3] := UTCval3;

And lastly, you can use a union to avoid using pointers:

(*
TYPE WORDS64 :
UNION
    words: ARRAY [0..3] OF WORD; // WORD <=> UINT (16 bit unsigned)
    word64: LWORD; // LWORD <=> ULINT (64 bit unsigned)
END_UNION
END_TYPE
*)

(* _words64: WORDS64; *)

_words64.words[0] := UTCval0;
_words64.words[1] := UTCval1;
_words64.words[2] := UTCval2;
_words64.words[3] := UTCval3;

UTCval := _words64.word64;
Guiorgy
  • 1,405
  • 9
  • 26
0

I think bit shift left (SHL) is what you're looking for.

UTCval := UINT_TO_ULINT(UTCval0) + SHL(UINT_TO_ULINT(UTCval1),16) + SHL(UINT_TO_ULINT(UTCval2),32) + SHL(UINT_TO_ULINT(UTCval3),48);

kolyur
  • 457
  • 2
  • 13