Работа со строками в CODESYS V3.5
МЭК 61131-3 устанавливает типы данных для программирования ПЛК. Они разделены на четыре основные категории: биты, числа, строки и временные типы.
Статья описывает работу со строками в среде CODESYS V3.5, используемой для программирования контроллеров ОВЕН СПК и ПЛК210.
Первые программируемые контроллеры были созданы в 60–70-х годах прошлого столетия, чтобы заменить электромеханические реле и аналоговые регуляторы. Изначально для разработки программ было достаточно двух основных типов данных: логического, который использовался для описания дискретных сигналов, и целочисленного, применявшегося для представления аналоговых сигналов. Однако развитие ПЛК привело к расширению спектра решаемых задач, что потребовало добавления новых типов данных, одним из которых стали строки.
Строки могут быть использованы для следующих целей:
- визуализация (создание таблиц с рецептами, сообщениями о тревогах и так далее);
- запись данных в файлы в виде, понятном человеку (формат CSV, JSON и так далее);
- реализация строковых протоколов обмена (DCON, MQTT и так далее);
- работа с SMS;
- хранение паролей, серийных номеров и так далее.
Типы строк в CODESYS V3.5
Строка представляет собой набор чисел, где каждое число соответствует отдельному символу. Связь между числами и символами определяется кодировкой. В CODESYS V3.5 представлены два типа строк: STRING и WSTRING. Основные параметры этих типов строк указаны в таблице 1.
Типы строк в CODESYS V3.5
|
Параметр |
STRING |
WSTRING |
|
Кодировка |
ASCII |
UCS-2 (Unicode) |
|
Размер символа |
1 байт |
2 байта |
|
Пример записи литерала (важен тип кавычек) |
‘hello, world’ |
“привет, мир” |
Выбор типа зависит от поставленной задачи. Например, для отображения строк в визуализации контроллеров ОВЕН следует применять только тип WSTRING. Если же вы работаете с SMS, то удобнее использовать STRING, поскольку при создании AT-команд для модемов применяется кодировка ASCII.
Размер и длина строки.
В CODESYS V3.5 при объявлении строки задаётся максимальное количество символов. Если это значение не указано, то по умолчанию используется 80 символов. Максимальное количество символов для строки явно не ограничено. Фактически длина строки ограничивается только объёмом памяти, выделенным под проект.
В CODESYS используются строки с нулевым завершением (как в языке C), то есть каждая строка заканчивается символом с кодом 0 (NUL-символом). Память под этот символ выделяется автоматически, и он не учитывается при объявлении переменной (пример 1).
VAR
// Максимальная длина – 40 символов
// Выделенная память – 41 байт
sMessage: STRING(40) := ‘test’;
// Максимальная длина – 80 символов (по умолчанию)
// Выделенная память – 162 байта
wsTitle: WSTRING := “test”;
END_VAR
Пример 1
Основные функции работы со строками.
Значение строковой переменной можно задать не только во время её объявления, но и в коде программы. Однако простого присваивания недостаточно. Для выполнения различных алгоритмов необходимы дополнительные действия, такие как объединение нескольких строк в одну, поиск определённого символа в строке и так далее. Для этих целей применяются стандартные функции из библиотеки 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);
Пример 2
Функции из библиотеки 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(Пример 3).
// неправильная конвертация
// 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]');
Пример 3
В библиотеке OSCAT Basic представлен широкий спектр функций для работы со строками. Некоторые из них похожи на функции из OwenStringUtils, но есть и уникальные, такие как отражение строки и преобразование числа в строку с его HEX-значением (пример 4). На сайте owen.ru в разделе CODESYS V3 доступна русскоязычная документация по этой библиотеке.
// sMessage получит значение ‘dcba’
sMessage := MIRROR(‘abcd’);
// sMessage получит значение ‘FF’
sMessage := BYTE_TO_STRH(255);
Пример 4
Управляющие символы.
Кроме видимых символов (букв, цифр, знаков пунктуации), строка может включать специальные символы, называемые управляющими последовательностями. Они позволяют, например, осуществить перенос строки для отображения нескольких сообщений в одном элементе визуализации.
В редакторе CODESYS для ввода специальных символов используется символ ‘$’ (пример 5). Полный перечень управляющих символов приведён в документации CODESYS V3.5. Визуализация.
sMessage := ‘Один$r$nДва’// Использование спецсимволов переноса строки
Пример 5
Строки и массивы.
Как было сказано в начале статьи, строка представляет собой массив символов. 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
Пример 6
Иногда возникает необходимость очистить строку. Для этого достаточно присвоить ей «пустое» значение. Однако следует помнить, что такая операция не удаляет все символы из строки — она лишь устанавливает нулевой терминатор в её первый символ. В примере 7 показано, как переменной сначала присваивается значение ‘ABCD’, которое затем заменяется пустой строкой.
Однако фактически происходит только обнуление первого символа строки, а коды остальных символов остаются на своих местах. Таким образом, если записать значение в первый элемент через индексный доступ, вы получите строку не из одного символа (как можно было бы ожидать), а из четырёх. Обычно подобные проблемы возникают при реализации строкового протокола обмена. Чтобы избежать их, следует использовать специальные функции для очистки строки (например, MemFill из библиотеки CAA Memory).
sMessage := ‘ABCD’;
sMessage := ‘’;
// sMessage получит значение ‘EBCD’
sMessage[0] := 16#45;
Пример 7
Заключение
В статье представлены основные аспекты работы со строками в среде CODESYS V3.5. Все упомянутые библиотеки можно загрузить на сайте owen.ru в разделе CODESYS V3. Подробные сведения о работе со строками содержатся в документации к этим библиотекам, а также в справочной системе среды программирования.
