При интеграции 1С с внешним оборудованием — кассовыми аппаратами, весовыми терминалами, промышленными контроллерами или датчиками — разработчики часто сталкиваются со специфическими форматами передачи данных. Одним из наиболее распространенных является BCD (Binary-Coded Decimal) или двоично-десятичный код. В отличие от стандартного двоичного представления, BCD кодирует каждую десятичную цифру отдельно, что удобно для вывода на дисплеи устройств, но требует особого алгоритма обработки в коде 1С.
В этой статье мы подробно разберем, как интерпретировать данные в формате BCD, проанализируем нюансы порядка байтов и напишем алгоритм для получения корректного числового значения.
Прежде чем переходить к написанию программного кода, нам необходимо разобраться в теории. Формат BCD бывает двух видов:
15 в упакованном BCD будет выглядеть в шестнадцатеричном виде как 0x15 (в двоичном: 0001 0101).Рассмотрим ситуацию, описанную в вопросе. Автор получает последовательность байтов 15 11 00 и флаг, указывающий на один знак после запятой. Итоговое число должно быть 111,5. Чтобы прийти к этому результату, нам нужно учитывать еще один важный технический параметр — порядок байтов (Endianness).
Проанализируем входные данные поэтапно. Ключом к разгадке является порядок Little-Endian. Это означает, что младшие разряды числа передаются первыми в потоке байтов.
Возьмем наши байты:
15 (содержит цифры 5 и 1)11 (содержит цифры 1 и 1)00 (содержит цифры 0 и 0)Если мы запишем их в обычном для человека порядке (от старшего к младшему), мы получим 00 11 15. Убираем лишние нули в начале и получаем 1115. Учитывая условие об одном знаке после запятой, получаем искомое 111,5. Теперь выясним, как реализовать этот процесс программно.
Для реализации парсера BCD нам потребуется выполнить следующие шаги для каждого полученного байта:
Рассмотрим пример функции на языке 1С, которая принимает массив байтов и возвращает числовое значение.
Функция ПреобразоватьИзBCD(МассивБайтов, КоличествоЗнаковПослеЗапятой) Экспорт
ИтоговоеЧисло = 0;
Множитель = 1;
// Перебираем байты в порядке их поступления (Little-Endian)
Для Каждого ТекущийБайт Из МассивБайтов Цикл
// Извлекаем младшую цифру (ниббл)
МладшаяЦифра = ТекущийБайт % 16;
// Извлекаем старшую цифру (ниббл)
СтаршаяЦифра = Цел(ТекущийБайт / 16);
// Валидация: в BCD не может быть цифр больше 9
Если МладшаяЦифра > 9 Или СтаршаяЦифра > 9 Тогда
// Здесь может быть логика обработки знака числа (A-F),
// но в простейшем случае это ошибка данных
Прервать;
КонецЕсли;
// Добавляем к результату
ИтоговоеЧисло = ИтоговоеЧисло + (МладшаяЦифра * Множитель);
Множитель = Множитель * 10;
ИтоговоеЧисло = ИтоговоеЧисло + (СтаршаяЦифра * Множитель);
Множитель = Множитель * 10;
КонецЦикла;
// Применяем положение запятой
Если КоличествоЗнаковПослеЗапятой > 0 Тогда
ИтоговоеЧисло = ИтоговоеЧисло / Pow(10, КоличествоЗнаковПослеЗапятой);
КонецЕсли;
Возврат ИтоговоеЧисло;
КонецФункции
Проанализируем ситуацию с данными 15 11 00 шаг за шагом:
Шаг 1: Обработка байта 15 (0x15)
МладшаяЦифра = 15 % 16 = 5. Добавляем к числу: 0 + 5 * 1 = 5. Множитель становится 10.
СтаршаяЦифра = Цел(15 / 16) = 1. Добавляем к числу: 5 + 1 * 10 = 15. Множитель становится 100.
Шаг 2: Обработка байта 11 (0x11)
МладшаяЦифра = 11 % 16 = 1. Добавляем к числу: 15 + 1 * 100 = 115. Множитель становится 1000.
СтаршаяЦифра = Цел(11 / 16) = 1. Добавляем к числу: 115 + 1 * 1000 = 1115. Множитель становится 10000.
Шаг 3: Обработка байта 00 (0x00)
Здесь обе цифры будут равны 0, итоговое значение не изменится и останется 1115.
Шаг 4: Запятая
Делим 1115 на 10^1 (так как 1 знак после запятой). Получаем 111,5. Задача решена!
При работе с реальным оборудованием важно помнить о нескольких моментах, которые могут усложнить задачу:
0xC — это плюс, а 0xD — это минус. Если вы видите, что функция возвращает странные значения при обработке последнего байта, проверьте документацию к вашему протоколу.10 (A) до 15 (F) считаются некорректными для цифр. Всегда добавляйте проверку Если Цифра > 9, чтобы избежать получения «мусорных» данных при сбоях связи.ЧислоИзШестнадцатеричнойСтроки() для преобразования каждого фрагмента в число перед обработкой.Таким образом, понимание структуры Packed BCD и порядка байтов Little-Endian позволяет легко интегрировать практически любое промышленное оборудование с системой 1С, обеспечивая высокую точность передачи числовых данных.