Строковые данные в регистрах Modbus
Как читать и записывать текст в регистрах Modbus: байты, пример ABCD, кодировка, заполнение, длина поля и проверка целостности длинной строки.

Серийный номер прибора читается без ошибок связи, но на экране вместо ABCD появляется BADC. В другом поле первые символы правильные, а после короткого названия остаётся хвост предыдущего текста. Такие дефекты часто относятся к представлению строк, а не к физической линии или контрольной сумме.
Разберём байты внутри регистров, кодировку, длину поля и заполнение остатка. Порядок слов чисел FLOAT здесь не рассматриваем. У строки свои границы: количество регистров не всегда равно числу символов, а нулевой байт не всегда означает конец данных.
Короткий ответ
Modbus передаёт содержимое 16-битных регистров, а способ размещения текста задаёт карта конкретного устройства. Для строки нужно знать адрес, число регистров, порядок байтов, кодировку и правило длины или завершения. В условном варианте ASCII строка ABCD занимает регистры 0x4142 и 0x4344. Перестановки исправляют по документации и проверочному образцу, сохраняя исходные значения для диагностики. При записи сначала согласуют полное поле и способ подтверждения, чтобы не оставить старый хвост или промежуточное содержимое.
Где заканчивается протокол и начинается формат прибора
Регистр содержит 16 бит. В протоколе определён порядок передачи байтов регистра, но из этого не следует универсальный формат строкового поля. Производитель может расположить два однобайтовых символа в слове, использовать один символ на регистр или добавить отдельное поле длины. Семантику задаёт документация приложения.
Поэтому настройка «Modbus big-endian» в драйвере не отвечает на все вопросы текста. Драйвер может уже преобразовать сетевые байты в числовые слова, после чего прикладной код извлекает символы. Если дополнительно поменять байты в двух местах, ошибка исчезнет на одном тесте и вернётся на другом.
Перед реализацией записывают договорённость: пространство регистров, стартовый адрес, длину блока, разрешённую функцию и формат текста. Отдельно уточняют, нумеруются ли адреса в руководстве с единицы или с нуля. Правильное декодирование блока, прочитанного со сдвигом на регистр, всё равно даст неправильную строку.
Название «строка 16» без единицы недостаточно. Это могут быть 16 байт, 16 символов или 16 регистров. Для ASCII различие между байтами и символами незаметно, а при многобайтовой кодировке становится критичным. Лучше уточнить формат до создания операторского поля и резервирования памяти.
Пример ABCD по шагам
Условимся, что устройство использует ASCII, два символа в регистре, старший байт содержит первый символ. Код A равен 0x41, B равен 0x42, C равен 0x43, D равен 0x44. Тогда первые два регистра должны содержать 0x4142 и 0x4344.
| Регистр | Старший байт | Младший байт | Полученный фрагмент |
|---|---|---|---|
| N | 0x41 | 0x42 | AB |
| N + 1 | 0x43 | 0x44 | CD |
| N + 2, если предусмотрен | 0x00 | 0x00 | Заполнение по принятому формату |
Если программа сначала извлекает младший байт, она получает BADC. Если меняет порядок регистров, получится CDAB. Если выполняет обе перестановки, результатом станет DCBA. Эти четыре варианта удобны для диагностики, поскольку каждый символ отличается и перестановку легко увидеть.
Чтение слова как десятичного числа тоже корректно на транспортном уровне. Но число 16706 не является строкой «AB», пока приложение не извлекло два байта и не применило кодировку. Для проверки сохраняют одновременно шестнадцатеричные слова, массив байтов и итоговый текст. Это позволяет локализовать преобразование.
Проверочный образец не должен состоять из одинаковых букв или симметричных пар. Строка AAAA скрывает любой порядок байтов, а ABBA скрывает часть перестановок. Лучше использовать разрешённую устройством последовательность с разными символами и нечётной длиной в отдельном тесте.
Длина, ноль и пробелы
В поле фиксированной длины неиспользованные позиции могут заполняться нулями, пробелами или специальным значением. Некоторые устройства отдают отдельную длину, другие используют завершающий ноль. Эти правила нельзя смешивать: обрезка по первому нулю неверна, если ноль имеет другое назначение или принадлежит многобайтовому представлению.
Допустим, поле занимает восемь байтов. Сначала в нём записали ABCDEFGH, затем XYZ. Если отправить только три новых байта, оставшаяся часть может остаться прежней. Получится XYZDEFGH. Перед записью короткой строки формируют весь разрешённый блок и заполняют остаток согласно карте устройства.
Удаление пробелов при выводе тоже требует решения. Концевые пробелы могут быть заполнением, а начальные или внутренние частью значимого артикула. Универсальный вызов очистки всех пробельных символов способен изменить идентификатор. Хранят исходный текст отдельно от представления, если формат имеет прикладное значение.
Для нечётного количества однобайтовых символов последний регистр содержит один символ и один байт заполнения. Его положение зависит от принятого порядка. В испытания включают пустую строку, один символ, нечётную длину и максимальное заполнение. Именно на краях обычно обнаруживаются лишний ноль или потерянная буква.
Кодировка и кириллица
ASCII не описывает кириллицу. Наличие русского интерфейса у прибора тоже не доказывает, что его Modbus-поле поддерживает UTF-8. В карте может быть задана другая кодовая страница или только ограниченный набор латинских символов. Неизвестную кодировку уточняют у производителя по конкретной версии прошивки.
В UTF-8 один видимый символ может занимать несколько байтов. Ограничение на 16 байтов поэтому не означает возможность записать 16 русских букв. Обрезка произвольного байтового массива способна разрезать последовательность внутри символа. Клиент должен проверять длину после кодирования и не создавать некорректный текст.
Для UTF-16 требуется знать порядок байтов кодовых единиц и правила работы со специальными последовательностями. Удалять каждый нулевой байт из такого представления нельзя: это разрушает данные. Поддержку Unicode включают только при подтверждённом формате прибора и совместимости принимающей среды.
Если устройство допускает только латинский артикул, интерфейс ввода должен явно сообщать ограничение и проверять допустимые знаки. Молчаливая замена кириллицы вопросительными знаками опасна для идентификаторов партии. Пользователь должен увидеть отказ записи или точное представление того, что будет отправлено.
Целостность чтения и записи
Один запрос чтения блока удобнее нескольких независимых операций, но сам по себе не доказывает атомарность обновления строки внутри устройства. Прибор может изменять регистры последовательно. Если поле динамическое, в документации ищут номер версии, признак готовности или иной механизм согласованного снимка.
При записи длинного поля нельзя предполагать, что последовательность нескольких запросов видна приложению как одна операция. Для имени рецепта или кода задания это существенно: процесс может увидеть смешение старых и новых частей. Используют штатный буфер, команду применения или другой предусмотренный протокол подтверждения.
После записи читают значение обратно, когда устройство разрешает такую проверку. Совпадение обратного чтения подтверждает содержимое поля, но не обязательно выполнение технологической команды. Если запись запускает действие, отдельно контролируют статус его принятия и завершения. Текстовое поле и команда не должны неявно подменять друг друга.
В журнал диагностики полезно помещать адрес, число регистров, исходные слова, выбранную кодировку и результат проверки длины. Секретные или персональные значения в диагностике ограничивают по правилам проекта. Для большинства технических идентификаторов достаточно хранить воспроизводимый тестовый образец, а не весь производственный поток.
Безопасные границы буфера
Перед преобразованием проверяют, что ответ содержит ожидаемое число регистров. Нельзя декодировать короткий ответ как полный блок, дополняя неизвестную часть случайным содержимым памяти. При отказе чтения итоговый текст сохраняют только как последнее известное значение с соответствующим качеством. Иначе старая строка может выглядеть новым серийным номером текущего изделия. Для идентификаторов такое смешение особенно неприятно: число ошибок связи останется небольшим, а прослеживаемость уже нарушится.
В программе полезно разделить три размера: физическую ёмкость массива, допустимую длину поля устройства и фактическую длину текста после декодирования. У каждого своя проверка. Увеличенный локальный буфер не разрешает записывать больше регистров в прибор. А корректная длина массива ещё не подтверждает корректность многобайтового символа в последней позиции. Проверки выполняют до отправки и до отображения.
Если поле содержит длину отдельным словом, её считают недоверенным входом и ограничивают паспортной ёмкостью. Значение длины может быть испорчено настройкой адреса или изменением версии прибора. Попытка прочитать столько байтов, сколько случайно пришло в регистре, создаёт выход за границы приложения. При превышении диапазона лучше показать конкретную ошибку формата и исходное слово длины, чем молча обрезать идентификатор.
Испытательная последовательность для строкового поля
Начинают с известного разрешённого образца, где различаются соседние символы. Проверяют сырые слова и итоговый текст без дополнительных преобразований интерфейса. Затем отправляют строку нечётной длины. Это позволяет проверить последний байт и заполнение. Следующий тест использует максимальную длину, чтобы обнаружить потерю последнего символа или ошибочное резервирование места под терминатор.
После длинной строки записывают короткую. Полное обратное чтение показывает, очищен ли остаток. Затем проверяют пустое значение, если прибор его допускает. Оно может означать очистку, отсутствие данных или недопустимый запрос, поэтому ожидаемый результат определяют заранее. Для записи служебного поля испытания проводят на разрешённом стенде, не меняя производственные идентификаторы без необходимости.
Отдельный набор касается запрещённых символов. Интерфейс должен отклонять неподдерживаемый ввод до записи либо явно показывать результат согласованного преобразования. Нельзя принимать текст на экране и незаметно отправлять другой идентификатор. Если допустима транслитерация, её правила фиксируют как часть прикладного формата, а не полагаются на случайную функцию операционной системы.
Последний тест проверяет отказ связи во время изменения поля. После восстановления читают фактическое содержимое и статус применения. Если протокол не обеспечивает атомарность, это ограничение должно быть видно в реализации. Успешная отправка первого фрагмента не является подтверждением полной записи, даже когда драйвер не выдал общую ошибку.
Как передать формат следующему разработчику
В карточке поля оставляют пример на уровне байтов, а не только скриншот имени. Для ABCD указывают ожидаемые два слова, порядок извлечения и правило заполнения следующих позиций. Рядом записывают адреса с пояснением системы нумерации. Такая карточка позволяет проверить любой новый драйвер без предположений о его внутренних настройках и представлении памяти.
При обновлении прошивки сравнивают описание карты и фактический контрольный образец. Если кодировка или длина изменились, прежнее приложение может продолжать получать корректные ответы Modbus и одновременно неверно понимать текст. Поэтому успешный обмен после обновления проверяют не только по отсутствию исключений, но и по смыслу нескольких известных значений. Для строк это такая же часть совместимости, как диапазон числового параметра.
Для идентификаторов важно проверить также регистр букв и ведущие нули. Значения AB001 и ab001 могут быть разными артикулами, а перевод текста в число уничтожит начальные нули. Преобразования интерфейса должны соответствовать прикладному договору. Если поле используется как ключ в базе, сохраняют его точное каноническое представление и правила сравнения. Отображаемая подпись может быть удобнее для человека, но не должна незаметно менять ключ. В испытания включают допустимые пробелы, дефисы и цифровые последовательности. После передачи через всю цепочку сравнивают конечный идентификатор с исходным, а не только его внешний вид на первом экране. При копировании между системами проверяют экранирование специальных символов и формат экспорта. Это отдельный участок после Modbus, который тоже способен испортить правильно прочитанную строку. Полный контрольный пример проходит от регистров прибора до фактического места использования данных.
Результаты контрольной проверки сохраняют вместе с точным обозначением оборудования, версией программы и фактическими настройками. Это позволяет повторить испытание после замены устройства и сравнить одинаковые условия, не опираясь только на воспоминания обслуживающей смены.
Вопросы при работе
Почему латиница правильная, а русский текст испорчен? Вероятно, различаются кодировки или ограничения поля. Проверяют реальные байты и паспорт формата. Перестановка регистров не является универсальным исправлением кодировки.
Нужно ли всегда добавлять нулевой терминатор? Только если этого требует устройство. Для поля точной длины лишний терминатор может выйти за границу и затронуть соседний параметр. Размер отправляемого блока проверяют до записи.
Можно ли декодировать массив слов напрямую как строку памяти ПЛК? Это зависит от представления памяти, строкового типа и порядка байтов среды. Надёжнее явно сформировать массив байтов и выполнить поддерживаемое преобразование с проверкой длины.
Почему после короткого имени остаются старые символы? Обычно не перезаписано всё поле или неверно обработано заполнение. Сравните полный блок регистров до и после записи и проверьте правило окончания строки.
