Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Data Types

IEC 61131-3 defines a rich set of elementary data types designed for industrial automation. This chapter covers every supported type, the type hierarchy, and the literal formats used to write constant values in code.

Boolean

TypeSizeValues
BOOL1 bitTRUE, FALSE
VAR
  motor_on : BOOL := TRUE;
  fault    : BOOL := FALSE;
END_VAR

Integer Types

Signed and unsigned integers come in four widths:

SignedUnsignedSizeRange
SINTUSINT8-bit-128..127 / 0..255
INTUINT16-bit-32768..32767 / 0..65535
DINTUDINT32-bit-2^31..2^31-1 / 0..2^32-1
LINTULINT64-bit-2^63..2^63-1 / 0..2^64-1
VAR
  temperature : INT  := -40;
  rpm         : UINT := 3600;
  big_count   : LINT := 1_000_000_000;
END_VAR

Underscores in numeric literals are allowed for readability.

Floating-Point Types

TypeSizePrecision
REAL32-bit~7 decimal digits
LREAL64-bit~15 decimal digits
VAR
  setpoint : REAL  := 72.5;
  pi       : LREAL := 3.14159265358979;
END_VAR

Bit-String Types

These types are used for bitwise operations and direct bit access:

TypeSize
BYTE8-bit
WORD16-bit
DWORD32-bit
LWORD64-bit
VAR
  status_flags : WORD  := 16#00FF;
  mask         : DWORD := 2#11110000_11110000_11110000_11110000;
END_VAR

Bit-string types are not interchangeable with integers. Use explicit conversions when mixing arithmetic and bitwise operations.

Time and Duration Types

TypeRepresentsExample literal
TIMEDurationT#5s, T#1h30m
DATECalendar dateD#2024-01-15
TODTime of dayTOD#14:30:00
DTDate and time combinedDT#2024-01-15-14:30:00
VAR
  cycle_time  : TIME := T#100ms;
  start_date  : DATE := D#2024-01-15;
  shift_start : TOD  := TOD#06:00:00;
  timestamp   : DT   := DT#2024-01-15-08:00:00;
END_VAR

Caveat: The keyword DT is a reserved type name. If you name a variable dt, it will conflict with the DT keyword. Since keywords are case-insensitive, dt, Dt, and DT all refer to the type. Use descriptive names like date_time or my_dt instead.

TIME literal components

A TIME literal begins with T# or TIME# followed by one or more components:

  • d – days
  • h – hours
  • m – minutes
  • s – seconds
  • ms – milliseconds
  • us – microseconds
  • ns – nanoseconds
VAR
  short_delay : TIME := T#250ms;
  work_shift  : TIME := T#8h;
  precise     : TIME := T#1m30s500ms;
END_VAR

String Types

TypeEncodingDefault max length
STRINGSingle-byte80 characters
WSTRINGUTF-1680 characters
VAR
  name    : STRING      := 'Hello, PLC!';
  label   : STRING[200] := 'Extended length string';
  unicode : WSTRING     := "Wide string literal";
END_VAR

Single-byte strings use single quotes. Wide strings use double quotes.

Type Hierarchy

The IEC 61131-3 type system is organized hierarchically:

ANY
├── ANY_BIT
│   ├── BOOL
│   ├── BYTE
│   ├── WORD
│   ├── DWORD
│   └── LWORD
├── ANY_NUM
│   ├── ANY_INT
│   │   ├── ANY_SIGNED (SINT, INT, DINT, LINT)
│   │   └── ANY_UNSIGNED (USINT, UINT, UDINT, ULINT)
│   └── ANY_REAL (REAL, LREAL)
├── ANY_STRING (STRING, WSTRING)
├── ANY_DATE (DATE, TOD, DT)
└── ANY_DURATION (TIME)

The ANY_* groups are used in function signatures to accept a range of types. For example, an ADD function accepts ANY_NUM inputs.

Literal Formats

Integer literals

BasePrefixExampleDecimal value
Decimal(none)255255
Hex16#16#FF255
Octal8#8#7763
Binary2#2#101010
VAR
  dec_val : INT   := 100;
  hex_val : INT   := 16#64;
  oct_val : INT   := 8#144;
  bin_val : INT   := 2#01100100;
END_VAR
// All four variables hold the value 100.

Real literals

Real numbers use a decimal point and optional exponent:

VAR
  a : REAL := 3.14;
  b : REAL := 3.14e2;    // 314.0
  c : REAL := 1.0E-3;    // 0.001
  d : REAL := -2.5e+10;
END_VAR

Typed literals

A typed literal forces a specific type on a constant value:

VAR
  x : INT  := INT#42;
  y : REAL := REAL#3.14;
  z : BYTE := BYTE#16#FF;
  w : BOOL := BOOL#1;
END_VAR

This is especially useful in function calls where overload resolution needs a hint, or when assigning to a generic (ANY_NUM) parameter.

Implicit Conversions

Narrowing conversions (e.g., DINT to INT) are not implicit and require an explicit conversion function like DINT_TO_INT(). Widening conversions (e.g., INT to DINT) are generally safe and may be performed implicitly by the compiler.

VAR
  small : INT  := 42;
  big   : DINT;
  back  : INT;
END_VAR

big  := small;              // OK: widening, implicit
back := DINT_TO_INT(big);   // Required: narrowing, explicit