Literals
Literals are fixed values written directly in your source code. TSharkRex supports integer, floating-point, time, string, and boolean literals. Understanding the correct syntax for each type is essential - especially hexadecimal notation, which you will use extensively when working with CAN data and hardware registers.
Integer Literals
Integer literals represent whole numbers. They can be written in decimal or hexadecimal notation, and may be negative.
Decimal Integers
Standard base-10 numbers, optionally prefixed with a minus sign for negative values:
VAR
speed : INT := 123;
offset : INT := -45;
bigVal : DINT := 1000000;
END_VAR;
Hexadecimal Integers
Hexadecimal literals use the 0x prefix. This is the dominant notation in
TSharkRex code because CAN IDs, byte masks, and register addresses are almost always
expressed in hex.
VAR
canId : DINT := 0x1F002E80;
mask : BYTE := 0xFF;
flag : BYTE := 0x01;
pattern : INT := 0x00FA;
END_VAR;
0x prefix for hexadecimal values.
Some IEC 61131-3 implementations use 16# instead - that syntax is
not supported here.
Boolean Values as Integers
TRUE and FALSE are integer literals equal to 1 and
0 respectively. They can appear anywhere an integer is expected:
VAR
active : BOOL := TRUE; // 1
stopped : BOOL := FALSE; // 0
END_VAR;
A practical example combining integer literal forms:
VAR
canId : DINT := 0x320;
dlc : BYTE := 8;
enabled : BOOL := TRUE;
retryCount : INT := 3;
errorCode : INT := -1;
SENDDATA : ARRAY[0..7] OF BYTE;
CANSEND : CAN_TX;
END_VAR;
IF enabled THEN
SENDDATA[0] := 0xFA;
SENDDATA[1] := 0x55;
CANSEND(ENABLE := TRUE, ID := canId, EXT := FALSE, DATALENGTH := dlc, DATA := SENDDATA);
END_IF;
Floating-Point Literals
TSharkRex supports two floating-point precisions. A plain decimal number produces a
REAL (single precision, 32-bit). Appending the suffix d produces
an LREAL (double precision, 64-bit).
VAR
voltage : REAL;
precise : LREAL;
factor : REAL;
temp : REAL;
END_VAR;
// Single precision (REAL) - assign in code body, not in VAR
voltage := 3.14;
precise := 3.14d; // Double precision (LREAL) - use d suffix
factor := 0.001;
temp := -25.5;
REAL for most purposes. Switch to LREAL
(with the d suffix) only when you need extra precision - for example,
accumulating very small increments over long periods.
Floating-point literals in expressions:
VAR
rawAdc : INT;
scaledVoltage : REAL;
calibrationOffset : REAL;
END_VAR;
calibrationOffset := 0.05;
// Convert a raw ADC reading to voltage
scaledVoltage := SINT_TO_FP(rawAdc, REAL) * 0.001 + calibrationOffset;
Time Literals
Time literals express durations using the T# prefix followed by one or more
time components. The general format is:
T#[days]d[hours]h[minutes]m[seconds]s[milliseconds]ms
Each component is optional, but at least one must be present. Components can be combined in any order (though by convention they appear from largest to smallest unit).
Basic Time Examples
T#1s // 1 second (1000 ms)
T#500ms // 500 milliseconds
T#2m30s // 2 minutes and 30 seconds
T#1h30m // 1 hour and 30 minutes
T#1d12h // 1 day and 12 hours
Underscore Separators
You can use underscores between components for readability. They are ignored by the compiler:
T#2s_500ms // 2.5 seconds
T#1h_30m_15s // 1 hour, 30 minutes, 15 seconds
Combined Time Literal
The most complete form uses all components:
T#10d10h10m10s10ms // 10 days, 10 hours, 10 minutes, 10 seconds, 10 ms
TIME values are stored internally as
UDINT (unsigned 32-bit integer) representing the total number of milliseconds.
This means T#1s is stored as 1000, and the maximum representable
duration is approximately 49.7 days.
Time literals are most commonly used with timer function blocks:
VAR_SIGNAL
SIGNAL_TANDNING : BOOL; // Ignition signal
END_VAR;
VAR
debounceTimer : TON;
blinkTimer : TON;
isActive : BOOL;
blinkState : BOOL;
END_VAR;
// Debounce an input signal for 200 ms
debounceTimer(IN := SIGNAL_TANDNING, PT := T#200ms);
isActive := debounceTimer.Q;
// Create a 500ms blink pattern
blinkTimer(IN := NOT blinkTimer.Q, PT := T#500ms);
blinkState := blinkTimer.Q;
String Literals
String literals are enclosed in double quotes. They support the \n escape
sequence for newlines:
"Hello World"
"Line1\nLine2"
"CAN Error: timeout"
The STRING data type is not currently supported by the TSharkRex compiler. String literals (e.g., "Hello") can only be used in specific contexts such as description labels in VAR_OUTPUT declarations (e.g., HELLJUS ["Helljus"] : OUTPUT;). You cannot declare STRING variables or perform string operations in recipes.
Boolean Literals
The two boolean literals are TRUE and FALSE. They are equivalent
to the integer values 1 and 0, which means they can participate
in arithmetic expressions.
VAR
isRunning : BOOL := TRUE;
isStopped : BOOL := FALSE;
multiplier : INT;
END_VAR;
// Boolean in arithmetic: TRUE = 1, FALSE = 0
multiplier := isRunning * 1000; // 1000 when running, 0 when stopped
This property is useful for conditional scaling without an IF statement:
VAR
SIGNAL_HELLJUS : BOOL;
SIGNAL_HALVLJUS : BOOL;
outputLevel : INT;
END_VAR;
// Combine boolean flags into a priority value
// HELLJUS (high beam) = 2, HALVLJUS (low beam) = 1, neither = 0
outputLevel := SIGNAL_HELLJUS * 2 + SIGNAL_HALVLJUS * 1;
Summary
| Literal Type | Examples | Stored As |
|---|---|---|
| Decimal integer | 123, -45 |
INT, DINT, BYTE |
| Hexadecimal integer | 0x1F, 0xFF00 |
INT, DINT, BYTE |
| Boolean | TRUE, FALSE |
BOOL (1 or 0) |
| Single-precision float | 3.14, 0.001 |
REAL (32-bit) |
| Double-precision float | 3.14d |
LREAL (64-bit) |
| Time | T#1s, T#500ms |
UDINT (milliseconds) |
| String | "Hello" |
STRING (not yet supported as a data type; used in labels only) |