Общие сведения о языке ST

ST (Structured Text) – это текстовый язык высокого уровня общего назначения, по синтаксису схожий с языком Pascal. Удобен для программ, включающих числовой анализ или сложные алгоритмы. Может использоваться в программах, в теле функции или функционального блока, а также для описания действия и перехода внутри элементов SFC. Согласно IEC 61131-3 ключевые слова должны быть введены в символах верхнего регистра. Пробелы и метки табуляции не влияют на синтаксис, они могут использоваться везде.

Выражения в ST выглядят точно также, как и в языке Pascal:

[variable] := [value];

Порядок их выполнения – справа налево. Выражения состоят из операндов и операторов. Операндом является литерал, переменная, структурированная переменная, компонент структурированной переменной, обращение к функции или прямой адрес.

Типы данных

Согласно стандарту IEC 61131-3, язык ST поддерживает весь необходимый набор типов, аналогичный классическим языкам программирования. Целочисленные типы: SINT (char), USINT (unsigned char), INT (short int), UINT (unsigned int), DINT (long), UDINT (unsigned long), LINT (64 бит целое), ULINT (64 бит целое без знака). Действительные типы: REAL (float), LREAL (double). Специальные типы BYTE, WORD, DWORD, LWORD представляют собой битовые строки длиной 8, 16, 32 и 64 бит соответственно. Битовых полей в ST нет. К битовым строкам можно непосредственно обращаться побитно. Например:

a.3 := 1; (* Установить бит 3 переменной a *)

Логический тип BOOL может иметь значение TRUE или FALSE. Физически переменная типа BOOL может соответствовать одному биту. Строка STRING является именно строкой, а не массивом. Есть возможность сравнивать и копировать строки стандартными операторами. Например:

strA := strB;

Для работы со строками есть стандартный набор функций (см. приложение 2, раздел «Строковые операции с переменными типа STRING»).

Специальные типы в стандарте IEC определены для длительности (TIME), времени суток (TOD), календарной даты (DATE) и момента времени (DT).

В таблице 3.1 приведены значения по умолчанию, соответствующие описанным выше типам.

Таблица 3.1 – Значения по умолчанию для типов данных IEC 61131-3

Тип(ы) данных

Значение

BOOL, SINT, INT, DINT, LINT

0

USINT, UINT, UDINT, ULINT

0

BYTE, WORD, DWORD, LWORD

0

REAL, LREAL

0.0

TIME

T#0S

DATE

D#0001-01-01

TIME_OF_DAY

TOD#00:00:00

DATE_AND_TIME

DT#0001-01-01-00:00:00

STRING

‘’ (пустая строка)

По умолчанию, все переменные инициализируются нулем. Иное значение переменной можно указать явно при ее объявлении. Например:

str1: STRING := ‘Hello world’;

В определённых ситуациях при разработке программных модулей удобно использовать обобщения типов, т.е. общее именование группы типов данных. Данные обобщения приведены в таблице 3.2.

Таблица 3.2 – Обобщения типов данных IEC 61131-3

ANY

ANY_BIT

ANY_NUM

ANY_DATE

TIME

STRING

и другие типы данных

BOOL

BYTE

WORD

DWORD

LWORD

ANY_INT

ANY_REAL

DATE

TIME_OF_DAY

DATE_AND_TIME

INT

SINT

DINT

LINT

UINT

USINT

UDINT

ULINT

REAL

LREAL

Конструкции языка

К конструкциям языка ST относятся:

  • арифметические операции;

  • логические (побитовые) операции;

  • операции сравнения;

  • операция присвоения;

  • конструкция IF – ELSEIF – ELSE;

  • цикл FOR;

  • цикл WHILE;

  • цикл REPAET UNTIL;

  • конструкция CASE.

При записи арифметических выражений допустимо использование скобок для указания порядка вычислений. При записи выражений допустимо использовать переменные (локальные и глобальные) и константы.

Арифметические операции

К арифметическим операциям относятся:

  • «+» – сложение;

  • «-» – вычитание;

  • «*» – умножение;

  • «/» – деление;

  • «mod» – остаток от целочисленного деления.

Приоритет операций в выражениях указан в таблице 3.4 (чем выше приоритет, тем раньше исполняется операция).

Логические (побитовые) операции

К данным операциям относятся:

  • «OR» – Логическое (побитовое) сложение;

  • «AND» – Логическое (побитовое) умножение;

  • «XOR» – Логическое (побитовое) «исключающее ИЛИ»;

  • «NOT» – Логическое (побитовое) отрицание.

Операции сравнения

Поддерживаются следующие операции сравнения:

  • «=» – сравнение на равенство;

  • «<>» – сравнение на неравенство;

  • «>» – сравнение на больше;

  • «>=» – сравнение на не меньше;

  • «<» – сравнение на меньше;

  • «<=» – сравнение на не больше.

В качестве результата сравнения всегда используется значение типа BOOL.

Присвоение

Для обозначения присвоения используется парный знак «:=». В правой и левой части выражения должны быть операнды одного типа (автоматического приведения типов не предусмотрено). В левой части выражения (принимающая сторона) может быть использована только переменная. Правая часть может содержать выражение или константу.

В таблице 3.4 приведены приоритеты при выполнении описанных выше операций.

Таблица 3.4 – Приоритеты операций

Операция

Приоритет

Сравнения

1

Сложение, вычитание

2

Умножение, деление

3

OR

4

AND, XOR

5

NOT

6

Унарный минус

7

Вызов функции

8

Конструкция IF – ELSEIF – ELSE

Для описания некоторых конструкций языка удобно использовать фигурные и квадратные скобки. Считается, что:

  • выражение в фигурных скобках может использоваться ноль или больше раз подряд;

  • выражение в квадратных скобках не обязательно к использованию.

Конструкция IF-ELSEIF-ELSE имеет следующий формат:

IF <boolean expression> THEN <statement list>

[ELSEIF <boolean expression> THEN <statement list>]

[ELSE <statement list>]

END_IF;

Например:

IF Var <> 0

THEN Var := 1

ELSEIF Var > 0

THEN Var := 0;

ELSE Var := 10;

END_IF;

Конструкция допускает вложенность, т.е. внутри одного IF может быть еще один и т.д. Например:

IF Var > 10 THEN

IF Var < Var2 + 1

THEN Var := 10;

ELSE Var := 0;

END_IF;

END_IF;

Цикл FOR

Служит для задания цикла с фиксированным количеством итераций. Формат конструкции следующий:

FOR <Control Variable> := <expression1> TO <expression2>

[BY <expression3>] DO

<statement list>

END_FOR;

При задании условий цикла считается, что <Control Variable>, <expression1> … <expression3> имеют тип INT. Выход из цикла будет произведен в том случае, если значение переменной цикла превысит значение <expression2>. Например:

FOR i := 1 TO 10 BY 2 DO

k := k * 2;

END_FOR;

Оператор BY задает приращение переменной цикла (в данном случае i будет увеличиваться на 2 при каждом проходе по циклу). Если оператор BY не указан, то приращение равно 1. Например:

FOR i := 1 TO k / 2 DO

var := var + k;

k := k – 1;

END_FOR;

Внутри цикла могут использоваться другие циклы, операторы IF и CASE. Для выхода из цикла (любого типа) может использоваться оператор EXIT. Например:

FOR i := 1 TO 10 BY 2 DO

k := k * 2;

IF k > 20 THEN

EXIT;

END_IF;

END_FOR;

Примечание 1: Выражения <expression1> … <expression3> вычисляются до входа в цикл, поэтому изменения значений переменных, входящих в любое из этих выражений не приведет к изменению числа итераций. Например:

01: k := 10;

02: FOR I := 1 TO k / 2 DO

03: k := 20;

04: END_FOR;

В строке 3 производится изменение переменной k, но цикл все равно выполнится только пять раз. Примечание 2: Значение переменной цикла может изменяться внутри тела цикла, но в начале очередной итерации значение данной переменной будет выставлено в соответствие с условиями цикла. Например:

01: FOR I := 1 TO 5 DO

02: I := 55;

03: END_FOR;

При первом проходе значение I будет равно 1, потом в строке 2 изменится на 55, но на втором проходе значение I станет равно 2 – следующему значению по условиям цикла.

Цикл WHILE

Служит для определения цикла с предусловием. Цикл будет исполняться до тех пор, пока выражение в предложении WHILE возвращает TRUE. Формат конструкции следующий:

WHILE <Boolean-Expression> DO

<Statement List>

END_WHILE;

Значение <Boolean-Expression> проверяется на каждой итерации. Завершение цикла произойдет, если выражение <Boolean-Expression> вернет FALSE. Например:

k := 10;

WHILE k > 0 DO

i := I + k;

k := k –1;

END_WHILE;

Внутри цикла могут использоваться другие циклы, операторы IF и CASE. Для досрочного завершения цикла используется оператор EXIT (см. пример в описание цикла FOR).

Цикл REPEAT UNTIL

Служит для определения цикла с постусловием. Завершение цикла произойдет тогда, когда выражение в предложении UNTIL вернет FALSE. Другими словами: цикл будет выполняться, пока условие в предложении UNTIL не выполнятся. Формат конструкции следующий:

REPEAT

<Statement List>

UNTIL <Boolean Expression>;

END_REPEAT;

Например:

k := 10;

REPEAT

i := i + k;

k := k – 1;

UNTIL k = 0;

END_REPEAT;

Внутри цикла могут использоваться другие циклы, операторы IF и CASE. Для досрочного завершения цикла используется оператор EXIT (см. пример в описании цикла FOR).

Конструкция CASE

Данная конструкция служит для организации выбора из диапазона значений. Формат конструкции следующий:

CASE <Expression> OF

CASE_ELEMENT {CASE_ELEMENT}

[ELSE <Statement List>]

END_CASE;

CASE_ELEMENT – это список значений, перечисленных через запятую. Элементом списка может быть целое число или диапазон целых чисел. Диапазон задается следующим образом BEGIN_VAL .. END_VAL.

Если текущее значение <Expression> не попало ни в один CASE_ELEMENT, то управление будет передано на предложение ELSE. Если предложение ELSE не указано, то никаких действий выполнено не будет.

Значение <Expression> может быть только целым. Например:

01: CASE k OF

02: 1:

03: k := k * 10;

04: 2..5:

05: k := k * 5;

06: i := 0;

07: 6, 9..20:

08: k := k – 1;

09: ELSE

10: k := 0;

11: i := 1;

12: END_CASE;

Строка 4 содержит диапазон значений. Если значение k принадлежит числовому отрезку [2, 5], то будут выполнены строки 5 и 6.

В строке 7 использован список значений. Строка 8 выполнится, если значение k будет равно 6 или будет принадлежать числовому отрезку [9, 20].

Строки 10 и 11 будут выполнены в том случае, если k < 1, или 6 < k < 9, или k > 20 (в данном случае сработает предложение ELSE).

При задании списка значений необходимо выполнять следующие условия:

  • наборы значений внутри одного CASE не должны пересекаться;

  • при указании диапазона значений начало диапазона должно быть меньше его конца.

В таблице 3.5 приведены примеры кода записи правильной и неправильной записи конструкции CASE.

Действия, предусмотренные для обработки каждого из случаев CASE, могут использовать циклы, операторы IF и CASE.

Таблица 3.5 – Запись конструкции CASE

Неправильная запись

Правильная запись

01: CASE k OF

02: 1:

03: k := k * 10;

04: 2..5:

05: k := k * 5;

06: i := 0;

07: 5, 9..20:

08: k := k – 1;

09: ELSE

10: k := 0;

11: i := 1;

12: END_CASE;

Диапазоны в строках 4 и 7 пересекаются

01: CASE k OF

02: 1:

03: k := k * 10;

04: 2..5:

05: k := k * 5;

06: i := 0;

07: 6, 9..20:

08: k := k – 1;

09: ELSE

10: k := 0;

11: i := 1;

12: END_CASE;

01: CASE k OF

02: 1:

03: k := k * 10;

04: 2..5:

05: k := k * 5;

06: i := 0;

07: 6, 20..9:

08: k := k – 1;

09: ELSE

10: k := 0;

11: i := 1;

12: END_CASE;

В строке 7 диапазон значений задан неправильно.

01: CASE k OF

02: 1:

03: k := k * 10;

04: 2..5:

05: k := k * 5;

06: i := 0;

07: 6, 9..20:

08: k := k – 1;

09: ELSE

10: k := 0;

11: i := 1;

12: END_CASE;

При написании программ на ST возможно использование стандартных и пользовательских функций и функциональных блоков.