Общие сведения о языке ST ========================= .. contents:: Содержание **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 | ANY\_INT | ANY\_REAL | DATE | | | | | | | BYTE | | | TIME\_OF\_DAY | | | | | | | WORD | | | DATE\_AND\_TIME | | | | | | | DWORD | | | | | | | | | | LWORD | | | | +------------+------------+-------------+------------------------+ | | INT | UINT | REAL | | | | | | | | SINT | USINT | LREAL | | | | | | | | DINT | UDINT | | | | | | | | | LINT | ULINT | | +------------+------------+-------------+------------------------+ Конструкции языка ----------------- К конструкциям языка 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 THEN [ELSEIF THEN ] [ELSE ] 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 := TO [BY ] DO END\_FOR; При задании условий цикла считается, что , имеют тип INT. Выход из цикла будет произведен в том случае, если значение переменной цикла превысит значение . Например: 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: Выражения вычисляются до входа в цикл, поэтому изменения значений переменных, входящих в любое из этих выражений не приведет к изменению числа итераций. Например: 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 DO END\_WHILE; Значение проверяется на каждой итерации. Завершение цикла произойдет, если выражение вернет 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 UNTIL ; END\_REPEAT; Например: k := 10; REPEAT i := i + k; k := k – 1; UNTIL k = 0; END\_REPEAT; Внутри цикла могут использоваться другие циклы, операторы IF и CASE. Для досрочного завершения цикла используется оператор EXIT (см. пример в описании цикла FOR). Конструкция CASE ^^^^^^^^^^^^^^^^ Данная конструкция служит для организации выбора из диапазона значений. Формат конструкции следующий: CASE OF CASE\_ELEMENT {CASE\_ELEMENT} [ELSE ] END\_CASE; CASE\_ELEMENT – это список значений, перечисленных через запятую. Элементом списка может быть целое число или диапазон целых чисел. Диапазон задается следующим образом BEGIN\_VAL .. END\_VAL. Если текущее значение не попало ни в один CASE\_ELEMENT, то управление будет передано на предложение ELSE. Если предложение ELSE не указано, то никаких действий выполнено не будет. Значение может быть только целым. Например: 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 | 01: CASE k OF | | | | | 02: 1: | 02: 1: | | | | | 03: k := k \* 10; | 03: k := k \* 10; | | | | | 04: 2..5: | 04: 2..5: | | | | | 05: k := k \* 5; | 05: k := k \* 5; | | | | | 06: i := 0; | 06: i := 0; | | | | | 07: 5, 9..20: | 07: 6, 9..20: | | | | | 08: k := k – 1; | 08: k := k – 1; | | | | | 09: ELSE | 09: ELSE | | | | | 10: k := 0; | 10: k := 0; | | | | | 11: i := 1; | 11: i := 1; | | | | | 12: END\_CASE; | 12: END\_CASE; | | | | | Диапазоны в строках 4 и 7 пересекаются | | +---------------------------------------------------+---------------------+ | 01: CASE k OF | 01: CASE k OF | | | | | 02: 1: | 02: 1: | | | | | 03: k := k \* 10; | 03: k := k \* 10; | | | | | 04: 2..5: | 04: 2..5: | | | | | 05: k := k \* 5; | 05: k := k \* 5; | | | | | 06: i := 0; | 06: i := 0; | | | | | 07: 6, 20..9: | 07: 6, 9..20: | | | | | 08: k := k – 1; | 08: k := k – 1; | | | | | 09: ELSE | 09: ELSE | | | | | 10: k := 0; | 10: k := 0; | | | | | 11: i := 1; | 11: i := 1; | | | | | 12: END\_CASE; | 12: END\_CASE; | | | | | В строке 7 диапазон значений задан неправильно. | | +---------------------------------------------------+---------------------+ При написании программ на ST возможно использование стандартных и пользовательских функций и функциональных блоков.