
Стандарт МЭК 61131-3 устанавливает основные типы данных, используемые при программировании ПЛК. Они подразделяются на четыре категории: биты, числа, строки и временные типы данных.
Данная статья посвящена работе со строковыми типами данных в среде CODESYS V3.5, которая используется для разработки программного обеспечения для контроллеров ОВЕН СПК и ПЛК210.
Первые программируемые логические контроллеры были разработаны в 1960–1970-х годах для замены электромеханических реле и аналоговых регуляторов. В те времена программирование основывалось всего на двух типах данных: логическом — для обработки дискретных сигналов, и целочисленном — для аналоговых сигналов. Однако с развитием ПЛК и расширением их функциональности возникла необходимость в добавлении новых типов данных, включая строки.
Строки используются в следующих задачах:
- отображение информации (создание таблиц рецептов, вывод сообщений о тревогах и т.д.);
- сохранение данных в человеко-читаемых форматах (например, CSV, JSON и др.);
- реализация строковых протоколов связи (таких как DCON, MQTT и т.д.);
- отправка SMS-сообщений;
- хранение паролей, серийных номеров и других данных.
Типы строк в CODESYS V3.5
Строки представляют собой массивы чисел, где каждое число соответствует конкретному символу в соответствии с выбранной кодировкой. В среде CODESYS V3.5 используются два типа строк: STRING и WSTRING.
Таблица 1. Характеристики типов STRING и WSTRING
Параметр | STRING | WSTRING |
Кодировка | ASCII | UCS-2 (Unicode) |
Размер символа | 1 байт | 2 байта |
Пример записи литерала (важен тип кавычек) | ‘hello, world’ | “привет, мир” |
Выбор типа зависит от решаемой задачи. Например, для отображения строк в визуализации контроллеров ОВЕН следует использовать только тип WSTRING. При работе с SMS удобнее применять STRING, так как при формировании AT-команд для модемов используется кодировка ASCII.
Длина и размер строки
В CODESYS V3.5 при объявлении строки задается ограничение числа ее символов. Если число символов не указано, то по умолчанию используется значение 80. Ограничение максимального числа символов строки в явном виде отсутствует. Фактически длина строки ограничена только объемом памяти, выделенной под проект.
В CODESYS используются нуль-терминированные строки (как в языке С), то есть каждая строка завершается NUL-символом
с кодом «0». Память под этот символ выделяется автоматически, и он не учитывается при объявлении переменной
VAR
// Максимальная длина – 40 символов
// Выделенная память – 41 байт
sMessage: STRING(40) := ‘test’;
// Максимальная длина – 80 символов (по умолчанию)
// Выделенная память – 162 байта
wsTitle: WSTRING := “test”;
END_VAR
Базовые функции работы со строками
Значение строковой переменной можно присвоить не только при ее объявлении, но и в коде программы. Однако одного присваивания недостаточно. Для реализации алгоритмов требуются дополнительные операции, например, объединение нескольких строк в одну, поиск в строке нужного символа и т.д. Для этих операций используются базовые функции из библиотеки Standard. Список этих функций с кратким описанием представлен в Таблице 2, использование – в Примере 2.
Таблица 2. Строковые функции библиотеки Standard
Функция | Краткое описание |
CONCAT (STR1, STR2) | Объединяет две строки в одну |
DELETE (STR, LEN, POS) | Удаляет из строки заданное число символов с нужной позиции |
FIND (STR1, STR2) | Производит поиск подстроки в строке |
INSERT (STR1, STR2, POS) | Добавляет подстроку в строку с заданной позиции |
LEFT (STR, SIZE) | Выделяет из строки подстроку заданной длины (начиная с первого символа) |
LEN (STR) | Вычисляет длину строки |
MID (STR, LEN, POS) | Выделяет из строки подстроку заданной длины (начиная с нужной позиции) |
REPLACE (STR1, STR2, LEN, POS) | Заменяет в строке один фрагмент на другой (начиная с нужной позиции) |
RIGHT (STR, SIZE) | Выделяет из строки подстроку заданной длины (начиная с последнего символа) |
sVar1 := ‘Hello, ’;
sVar2 := ‘world’;
// sVar3 теперь имеет значение ‘Hello, world’
sVar3 := CONCAT(sVar1, sVar2);
// iLen будет иметь значение 12
iLen := LEN(sVar3);
Функции из библиотеки Standard предназначены для работы исключительно с переменными типа STRING. Для обработки строк типа WSTRING используется библиотека Standard64, в которой представлен аналогичный набор функций с префиксом «W» (например, WCONCAT, WDELETE и другие).
Расширенные функции работы со строками
Следует учитывать, что функции библиотек Standard и Standard64 способны обрабатывать только строки длиной до 255 символов. Для работы с более длинными строками рекомендуется использовать библиотеку StringUtils. Эта библиотека принимает в качестве аргументов не сами строки, а указатели на них. Также она включает дополнительные функции, такие как преобразование строк в верхний или нижний регистр, удаление пробелов и прочие.
Конвертация строковых типов
Типы строк STRING и WSTRING ориентированы на работу с различными кодировками (подробнее см. Таблицу 1). В ряде случаев требуется преобразование между этими типами. Например, строка-сообщение типа WSTRING, используемая в визуализации, может быть отправлена по SMS как значение типа STRING. Однако стандартные операторы конверсии STRING_TO_WSTRING и WSTRING_TO_STRING в этом случае неприменимы, так как они не выполняют преобразование кодировок, а лишь переносят содержимое памяти одной переменной в другую.
Для решения подобных задач используется библиотека OwenStringUtils, разработанная компанией ОВЕН. Эта библиотека предоставляет следующие возможности:
- конвертацию кодировок (см. Пример 3);
- работу с подстроками;
- форматирование вывода переменных типов DATE, TOD, DT, REAL
// неправильная конвертация
// wsMessage получит значение "òåñò"
wsMessage := TO_WSTRING('тест');
// правильная конвертация
// wsMessage получит значение "тест"
wsMessage := OSU.CP1251_TO_UNICODE('тест');
// sDateTime получит значение '02.04.2019 08:11:30'
dtDateTime := DT#2019-04-02-08:11:30;
sDateTime := OSU.DT_TO_STRING_FORMAT (dtDateTime, '%t[dd.MM.yyyy HH:mm:ss]');
Большой набор функций для работы со строками можно найти в библиотеке OSCAT Basic. Часть из них повторяет функционал OwenStringUtils, но присутствуют и уникальные: например, зеркалирование строки и преобразование числа в строку с его
HEX-значением (Пример 4). Русскоязычное описание библиотеки доступно на сайте owen.ru в разделе CODESYS V3.
// sMessage получит значение ‘dcba’
sMessage := MIRROR(‘abcd’);
// sMessage получит значение ‘FF’
sMessage := BYTE_TO_STRH(255);
Управляющие последовательности
Помимо видимых символов (букв, цифр, знаков препинания) строка может содержать спецсимволы, которые называются управляющими последовательностями. С их помощью, например, можно организовать перевод строки для вывода нескольких сообщений в одном элементе визуализации.
В редакторе CODESYS для ввода спецсимволов используется знак ‘$’ (Пример 5). Полный список спецсимволов приведен в документе CODESYS V3.5. Визуализация.
sMessage := ‘Один$r$nДва’// Использование спецсимволов переноса строки
Строки и массивы
Как было сказано в начале статьи, строка представляет собой массив символов. CODESYS V3.5 позволяет осуществлять индексный доступ к строке – как к массиву значений типа BYTE (для STRING) или WORD (для WSTRING). Это удобно при работе с файлами и реализацией протоколов обмена. В Примере 6 демонстрируется обработка строки в цикле FOR для определения позиций символов, разделяющих значения. Это может потребоваться при чтении информации из файлов формата «.csv».
VAR
sRecord: STRING := '123;456;789';
sSeparatorChar: STRING := ';';
auiSeparatorPos: ARRAY [0..10] OF INT;
i: INT;
j: INT;
END_VAR
j := 0;
FOR i:= 0 TO LEN(sRecord) DO
IF sRecord[i] = sSeparatorChar[0] THEN
auiSeparatorPos[j] := i;
j := j + 1;
// TODO: добавить проверку
// для верхней границы массива
END_IF
END_FOR
В некоторых случаях требуется очистить строку. Для этого достаточно присвоить ей «пустое» значение. Но следует учитывать, что эта операция не очищает строку полностью – она только записывает NUL-терминатор в ее начальный символ. В примере 7 продемонстрирована ситуация, когда переменной сначала присваивается значение ‘ABCD’, которое потом перезаписывается пустой строкой.
Но фактически происходит только обнуление начального символа строки, а коды остальных символов остаются на своих местах. Поэтому, записав значение в начальный элемент через индексный доступ, вы получите строку не из одного символа (как могли ожидать), а из четырех. Обычно такие проблемы проявляются при реализации строкового протокола обмена. Чтобы избежать их, надо очищать строку с помощью специальных функций (например, MemFill из библиотеки CAA Memory).
sMessage := ‘ABCD’;
sMessage := ‘’;
// sMessage получит значение ‘EBCD’
sMessage[0] := 16#45;
Заключение
Рассмотрены ключевые моменты работы со строками в среде CODESYS V3.5. Все перечисленные библиотеки доступны для загрузки на сайте owen.ru в разделе CODESYS V3. Подробная информация о работе со строками приведена в документации к этим библиотекам, а также в справке среды программирования.