REFERENCE
A reference points implicitly to another object. The reference is implicitly dereferenced during the access and therefore requires no special content operator ^ like a pointer.
Syntax
<identifier> : REFERENCE TO <data type> ;
<data type> : base type of the reference
Sample declaration:
PROGRAM_MAIN
VAR
refInt : REFERENCE TO INT;
nA : INT;
nB : INT;
END_VAR
You can now use refInt as "alias" for variables of type INT.
Assignment:
You have to set the address of the reference via a separate assignment operation with the help of the assignment operator REF=. An exception to this is when an input is a REFERENCE TO and the input is transferred within the call. In this case the normal allocation operator := is used instead of the allocation operator REF=.
FUNCTION_BLOCK FB_Sample
VAR_INPUT
refInput1 : REFERENCE TO INT;
refInput2 : REFERENCE TO INT;
END_VAR
PROGRAM MAIN
VAR
fbSample : FB_Sample;
n1 : INT;
n2 : INT;
END_VAR
fbSample.refInput1 REF= n1;
fbSample(refInput2 := n2);
You can check whether a reference points to a valid value (e.g. not equal to 0) with the help of a special operator (see Checking references for validity).
Application example:
refInt REF= nA; // refInt points now to nA
refInt := 12; // nA has got the value 12
nB := refInt * 2; // nB has got the value 24
refInt REF= nB; // refInt points now to nB
refInt := nA / 2; // nB has got the value 6
refInt REF= 0; // explicit initialisation of the reference
TwinCAT initializes references (with 0). |
Allocation operator REF=
The operator generates a reference (pointer) to a value.
Syntax:
<variable name> REF= <variable name>
Sample:
PROGRAM MAIN
VAR
refA : REFERENCE TO ST_Sample;
stA : ST_Sample;
refB : REFERENCE TO ST_Sample;
stB1 : ST_Sample;
stB2 : ST_Sample;
END_VAR
refA REF= stA; // represents => refA := ADR(stA);
refB REF= stB1; // represents => refB := ADR(stB1);
refA := refB; // represents => refA^ := refB^; (value assignment of refB as refA and refB are implicitly dereferenced)
refB := stB2; // represents => refB^ := stB2; (value assignment of stB2 as refB is implicitly dereferenced)
END_VAR
Invalid declarations
PROGRAM MAIN
VAR
aTest : ARRAY[0..9] OF REFERENCE TO INT;
pTest : POINTER TO REFERENCE TO INT;
refTestRef : REFERENCE TO REFERENCE TO INT;
refTestBit : REFERENCE TO BIT;
END_VAR
A reference type may not be used as the base type of an array, pointer or a reference. In addition, a reference may not point to a bit variable. Such constructs generate compiler errors.
Comparison of reference and pointer
In comparison with a pointer, a reference has the following advantages:
- Easier to use:
- A reference can directly access the contents of the referenced object without dereferencing.
- Nicer and simpler syntax when transferring values:
- Calling a function block that transfers a reference without address operator instead of a pointer.
- Sample:
FB_Test1(refInput := nValue);
instead of:FB_Test2(pInput := ADR(nValue));
- Type safety:
- When assigning two references, the compiler checks whether the base types match. This is not checked in the case of pointers.
Checking references for validity
You can use the operator __ISVALIDREF
to check whether a reference points to a valid value, i.e. a value not equal to 0.
Syntax:
<boolesche Variable> := __ISVALIDREF(<mit REFERENCE TO <datatype> deklarierter Kennzeichner>);
The boolean variable becomes TRUE if the reference points to a valid value, otherwise FALSE.
Sample
PROGRAM_MAIN
VAR
nVar : INT;
refInt1 : REFERENCE TO INT;
refInt2 : REFERENCE TO INT;
bTestRef1 : BOOL := FALSE;
bTestRef2 : BOOL := FALSE;
END_VAR
nVar := nVar + 1;
refInt1 REF= nVar;
refInt2 REF= 0;
bTestRef1 := __ISVALIDREF(refInt1); (* becomes TRUE, because refInt1 points to nVar, which is non-zero *)
bTestRef2 := __ISVALIDREF(refInt2); (* becomes FALSE, because refInt2 is set to 0 *)
The implicit monitoring function Checkpointer acts on variables of the type |
Automatic pointer/reference update during Online Change
Available from TwinCAT 3.1 Build 4026 |
The following descriptions refer to both pointers and references. For ease of reading, however, only the term pointer is used in the following.
Function:
During an Online Change, the values of all PLC pointers are automatically updated so that the respective pointer refers to the same variable or the same object as before the Online Change. This means that a pointer remains valid after the Online Change, even if the variable it points to is moved to a different memory position during the Online Change.
Mode of operation:
During an Online Change, a check is made for each pointer to see whether it refers to a PLC symbol. The following requirements must be met for such a determination.
- Case 1: Symbol was determined
- If the symbol still exists in the new symbols that exist after the Online Change and if the type of the symbol has not changed, the pointer is moved to the symbol found. The pointer or address value is updated.
- If the symbol no longer exists in the new symbols or if the type of symbol has changed, the pointer is set to zero.
- Case 2: Symbol was not determined
- If a pointer refers to an address for which no symbol is found before the Online Change (e.g. because the pointer points to a memory area outside the PLC), the pointer value is not changed during the Online Change.
Requirements:
- This function requires the (ADS) symbol description of the variable to which the pointer points to. If there is no symbol description for a variable, e.g. due to the use of Attribute 'hide', the pointer is not taken into account.
- The pointer must point to a variable/object within the PLC memory. Pointers pointing to a memory area outside the PLC memory are not changed during Online Change.
Additional update option:
The functionality described is available from TwinCAT 3.1 Build 4026. Any previous, manually implemented mechanism for updating a pointer can still be used. The desired destination can be assigned to the pointer cyclically, for example. There is no need to remove these lines of code from the project. Similarly, it is not necessary to keep or implement these lines of code.
See also: