Как отправить бинарные команды в весы через COM-порт и MSCOMM в 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При подключении торгового оборудования, такого как электронные весы или фискальные регистраторы, через интерфейс RS-232 часто возникает задача прямой низкоуровневой отправки управляющих последовательностей. Для этого нередко используют стандартную библиотеку mscomm.ocx (ActiveX-компонента MsCommLib.MsComm). Проанализируем типичную проблему: как правильно передать байтовую последовательность (HEX/двоичные данные) в свойство драйвера Output, корректно настроить порт и обработать полученный ответ.

Инициализация и настройка порта через MSComm

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

Разберем базовую процедуру подключения:


Драйвер = Новый COMОбъект("MsCommLib.MsComm.1");
Драйвер.CommPort = Число(НомерПорта); // Например, 1 для COM1
Драйвер.Settings = СокрЛП(Скорость) + ",N,8,1"; // Например, "9600,N,8,1"
Драйвер.InputLen = 0; // Считывать весь буфер за один вызов
Драйвер.InputMode = 0; // 0 - comInputModeText, 1 - comInputModeBinary
Драйвер.NullDiscard = 0;
Драйвер.RThreshold = 0;
Драйвер.Handshaking = 0; // 0 - без подтверждения, 1 - XOnXOff, 2 - RTS/CTS
Драйвер.EOFEnable = Истина;

Если Драйвер.PortOpen = 1 Тогда
    Драйвер.PortOpen = 0;
КонецЕсли;

Драйвер.PortOpen = 1;

Параметр Handshaking задает протокол подтверждения связи. Допустимые значения:

  1. 0 (ComNone) — аппаратное и программное управление потоком отключено (значение по умолчанию).
  2. 1 (ComXOnXoff) — программный протокол обмена с символами паузы и возобновления передачи.
  3. 2 (ComRTS) — аппаратное подтверждение связи по линиям RTS/CTS.
  4. 3 (comRTSXOnXOff) — совмещенное аппаратное и программное подтверждение.

Способ 1. Надежная отправка бинарных данных через COMSafeArray (Рекомендуемый)

Самый надежный способ передать любую последовательность байтов (включая нулевые байты 0x00) — использовать типизированный массив COM. Если передавать команду обычной строкой, нулевой байт воспримется как символ окончания строки (null-terminator), и пакет будет обрезан. Компонента mscomm.ocx принимает бинарные массивы с типом элемента VT_UI1 (беззнаковый байт).

Разберем по шагам создание и отправку такого пакета:


// Создаем одномерный массив байтов COM нужной длины
РазмерПакета = 8;
ДвоичныйМассив = Новый COMSafeArray("vt_ui1", РазмерПакета);

// Заполняем массив десятичными кодами байтов
ДвоичныйМассив.Установить(0, 2);   // 0x02
ДвоичныйМассив.Установить(1, 5);   // 0x05
ДвоичныйМассив.Установить(2, 19);  // 0x13
ДвоичныйМассив.Установить(3, 30);  // 0x1E
ДвоичныйМассив.Установить(4, 0);   // 0x00
ДвоичныйМассив.Установить(5, 0);   // 0x00
ДвоичныйМассив.Установить(6, 0);   // 0x00
ДвоичныйМассив.Установить(7, 8);   // 0x08

// Отправляем пакет в устройство
Объект.Драйвер.Output = ДвоичныйМассив;

Такой подход полностью исключает искажение байтов выше 127 и обрезание пакета на нулевых значениях.

Способ 2. Формирование командной строки через преобразование HEX в символы

Если протокол весов ориентирован на текстовые команды или не содержит нулевых байтов, можно передавать данные в виде строки. Для преобразования строки HEX-кодов вида "02 05 13 1E 08" в последовательность символов используют функции перевода систем счисления и преобразования кодов в символы.

Рассмотрим реализацию вспомогательных функций:


Функция ToDec(Знач тЗначение, тОснование)
    тРезультат = 0;
    тДлина = СтрДлина(тЗначение);
    Для тСимвол = 1 По тДлина Цикл
        тМножитель = 1;
        Для тСчет = 1 По тДлина - тСимвол Цикл 
            тМножитель = тМножитель * тОснование;
        КонецЦикла;
        тРезультат = тРезультат + (Найти("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", ВРег(Сред(тЗначение, тСимвол, 1))) - 1) * тМножитель;
    КонецЦикла;
    Возврат Окр(тРезультат);
КонецФункции

Функция СимволКода(КодБайта)
    // Для стандартных кодов можно использовать штатную функцию Символ()
    // Либо выполнять генерацию через VBScript Chr() при необходимости строгой ANSI-кодировки
    Возврат Символ(КодБайта);
КонецФункции

Функция ВернутьСтрИзHex(СтрHex)
    Стр = СтрЗаменить(СтрHex, " ", Символы.ПС);
    Ткс = Новый ТекстовыйДокумент;
    Ткс.УстановитьТекст(Стр);
    Команда = "";
    Для н = 1 По Ткс.КоличествоСтрок() Цикл
        Слово = СокрЛП(Ткс.ПолучитьСтроку(н));
        Если ЗначениеЗаполнено(Слово) Тогда
            Команда = Команда + СимволКода(ToDec(Слово, 16));
        КонецЕсли;
    КонецЦикла;
    Возврат Команда;
КонецФункции

Отправка команды в порт в таком случае выглядит следующим образом:

Объект.Драйвер.Output = ВернутьСтрИзHex("02 05 13 1E 08");

Организация чтения ответа весов

После отправки команды порт переходит в режим ожидания ответа. Не следует использовать бесконечные блокирующие циклы без ограничения времени, так как это приводит к зависанию интерфейса платформы. Рекомендуется использовать цикл с ограничением по таймауту и проверкой количества поступивших байт через InBufferCount.

Посмотрим на пример безопасного опроса буфера:


Функция ПолучитьОтвет(Драйвер, ТаймаутСекунд = 3)
    ВремяНачала = ТекущаяДата();
    Ответ = "";
    
    Пока (ТекущаяДата() - ВремяНачала) < ТаймаутСекунд Цикл
        ОбработкаПрерыванияПользователя();
        
        Если Драйвер.InBufferCount > 0 Тогда
            Попытка
                Ответ = Ответ + Драйвер.Input;
            Исключение
                Сообщить("Ошибка чтения из буфера: " + ОписаниеОшибки());
                Прервать;
            КонецПопытки;
            
            // Если получен признак конца кадра (например, символ перевода строки), завершаем чтение
            Если Найти(Ответ, Символы.ВК) > 0 Или Найти(Ответ, Символы.ПС) > 0 Тогда
                Прервать;
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Ответ;
КонецФункции

Ограничения использования MSComm и современные альтернативы

При использовании mscomm.ocx важно учитывать следующие архитектурные особенности:

  1. Разрядность: Данная библиотека является исключительно 32-битной (x86). Она не работает под 64-разрядным клиентом 1С:Предприятия или на 64-разрядном сервере.
  2. Лицензирование: Для создания объекта MsCommLib.MsComm в среде Windows требуется наличие специального лицензионного ключа времени выполнения в реестре. На рабочих машинах без среды разработки библиотека может вызывать ошибку инициализации лицензии.
  3. Событийная модель: Попытка перехвата событий COM-порта через обработчик OnComm часто приводит к аварийному завершению платформы из-за межпотоковых конфликтов.

Если есть возможность выбора, для промышленной эксплуатации рекомендуется использовать компоненты на базе Native API от разработчиков торгового оборудования или типовую Библиотеку подключаемого оборудования (БПО), в которой протоколы взаимодействия с весами уже реализованы и отлажены на уровне сертифицированных драйверов.

← На главную