Как получить число из BCD формата в 1С

Программист IT и автоматизация бизнеса
← На главную

При интеграции 1С с внешним оборудованием — кассовыми аппаратами, весовыми терминалами, промышленными контроллерами или датчиками — разработчики часто сталкиваются со специфическими форматами передачи данных. Одним из наиболее распространенных является BCD (Binary-Coded Decimal) или двоично-десятичный код. В отличие от стандартного двоичного представления, BCD кодирует каждую десятичную цифру отдельно, что удобно для вывода на дисплеи устройств, но требует особого алгоритма обработки в коде 1С.

В этой статье мы подробно разберем, как интерпретировать данные в формате BCD, проанализируем нюансы порядка байтов и напишем алгоритм для получения корректного числового значения.

Понятие формата BCD и его разновидности

Прежде чем переходить к написанию программного кода, нам необходимо разобраться в теории. Формат BCD бывает двух видов:

  1. Распакованный (Unpacked BCD): Каждая десятичная цифра занимает целый байт. Это не очень эффективно с точки зрения памяти, так как используется только 4 бита из 8.
  2. Упакованный (Packed BCD): Это именно тот вариант, с которым столкнулся автор темы. В упакованном формате один байт содержит сразу две десятичные цифры. Байт делится на два «ниббла» (полубайта) по 4 бита каждый. Например, десятичное число 15 в упакованном BCD будет выглядеть в шестнадцатеричном виде как 0x15 (в двоичном: 0001 0101).

Рассмотрим ситуацию, описанную в вопросе. Автор получает последовательность байтов 15 11 00 и флаг, указывающий на один знак после запятой. Итоговое число должно быть 111,5. Чтобы прийти к этому результату, нам нужно учитывать еще один важный технический параметр — порядок байтов (Endianness).

Разбор ситуации: Почему "15 11 00" превращается в "111,5"

Проанализируем входные данные поэтапно. Ключом к разгадке является порядок Little-Endian. Это означает, что младшие разряды числа передаются первыми в потоке байтов.

Возьмем наши байты:

Если мы запишем их в обычном для человека порядке (от старшего к младшему), мы получим 00 11 15. Убираем лишние нули в начале и получаем 1115. Учитывая условие об одном знаке после запятой, получаем искомое 111,5. Теперь выясним, как реализовать этот процесс программно.

Алгоритм извлечения данных в 1С

Для реализации парсера BCD нам потребуется выполнить следующие шаги для каждого полученного байта:

  1. Выделить младший ниббл (правую цифру). Математически это выполняется как остаток от деления значения байта на 16.
  2. Выделить старший ниббл (левую цифру). Это результат целочисленного деления значения байта на 16.
  3. Учесть позицию байта в последовательности, чтобы придать цифрам нужный «вес» (десятки, сотни, тысячи и т.д.).

Рассмотрим пример функции на языке 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. Задача решена!

Дополнительные нюансы: знаки и валидация

При работе с реальным оборудованием важно помнить о нескольких моментах, которые могут усложнить задачу:

Таким образом, понимание структуры Packed BCD и порядка байтов Little-Endian позволяет легко интегрировать практически любое промышленное оборудование с системой 1С, обеспечивая высокую точность передачи числовых данных.

← На главную