Как записать упакованные двоично-десятичные числа на старый прибор (гауссметр Varian FR41) с помощью LabVIEW?

В настоящее время я пытаюсь связаться со старым прибором, который использует только упакованные числа BCD (это гауссметр контроллера Varian FR41, если кто-то знаком). Я использую LabVIEW для репликации некоторого старого кода C, который выводит код BCD. Ниже приведен сценарий C. Он выполняет простые арифметические действия для генерации целых чисел, которые экспортируются в прибор через порт IEEE с использованием %c.

#include "ieeeio.h"
#include <math.h>
#include <stdio.h>


main()

{
  long  temp;
  int   z1,z2,z3,z4,b1,b2,b3;
  float b;
  double gauss,hv=5000.,magconst=.069,Mass=87.;

  if (ieeeinit()==-1)
  {
    printf("Cannot initialize IEEE system.\n");
    exit(1);
  }
  gauss=sqrt(Mass*hv/magconst);
  temp=10*gauss;
  b=temp/10.;
  z1=b/1000;
  z2=b/100;
  z3=b/10;
  z4=b;
  printf("\n\r %f %f %d %d %d %d",gauss,b,z1,z2,z3,z4);
  b1=z2+z1*6;
  b2=z4+6*z3-160*z2;
  b3=(b-z4)*160+14;
  printf("\n\r %d %d %d %d",7,b1,b2,b3);
  ieeewt("output 08;");
  ieeeprtf("%c%c%c%c\n",7,b1,b2,b3);
}

Я сгенерировал .VI, который генерирует те же числа b1,b2,b3 и помещает их в строку упакованных чисел BCD. Используя входные переменные HV,magconst,mass выше, выход должен быть 2510.8 gauss. и b1,b2,b3 равны 142,37,16 соответственно.

Теперь о том, чего хочет Varian Gaussmeter. Это текст, описывающий, как прибор получает информацию (не все это полезно, но для полноты картины копирую). Я также прилагаю изображение схемы, которая показывает формат BCD. Формат для BCD из руководства

Данные передаются на FR-41 в виде последовательности из трех 8-битных байтов. Каждый байт делится на два полубайта, hi и lo, которые могут содержать только двоично-десятичные числа. Когда используется вспомогательный порт вывода, к началу последовательности добавляется четвертый байт (любое двоичное число). Последний отправленный символ содержит младшую значащую цифру (LSD) новой настройки Гаусса в старшем байте и недвоично-десятичный символ управления загрузкой (ячейка 14) в младшем байте, который интерпретируется как загружающий все регистры новыми данными. Один бит младшего байта при использовании управляет превышением диапазона 10 кГаусс. никакое изменение настройки не происходит до тех пор, пока не будет получено управляющее слово.

Итак, если я правильно понимаю это в приведенном выше коде C, первый добавленный байт (вещь с вспомогательным выходным портом), кажется, равен 7, что должно быть 0000 0111 в BCD. Следующие байты для записи 2510.8 должны быть 0010 0101 0001 0000 1000, за которыми следует 1110 (для контрольного слова ячейки 14).

Вот что я сделал. Используя прилагаемый .VI, я могу воспроизвести 32-битную строку BCD, которая, как я ожидаю, должна быть. Я отправляю это в ВП GPIB Send Message в LabVIEW (я также пытался использовать VISA Write, но, насколько я вижу, он делает то же самое во всех тестах). Однако прибор ничего не регистрирует.

Интересно то, что когда я отправляю прибору информацию в виде строки %f с плавающей запятой, то есть 7.0000142.00037.00016.000, прибор регистрирует что-то происходящее и меняются десятки и сотни разрядов. Итак, если я отправлю 42 в виде числа с плавающей запятой, прибор перейдет к настройке гаусса X4X2.X. Если я поставлю 142, будет то же самое. Если я поставлю 17, он перейдет к настройке X1X7.X. Если я отправлю 17, то 25 будет принят только первый.

Я думаю, что что-то в GPIB Send или VISA Write берет мою строку чисел BCD и отправляет их как что-то еще, но я не могу понять, что я мог делать неправильно. Любая помощь или тесты будут высоко оценены; Я боролся с этим уже несколько недель, но безрезультатно. VI для воспроизведения C-скрипта, скопированного выше


person Jesse    schedule 02.11.2019    source источник


Ответы (1)


Как вы написали, значение 2510.8 должно быть отправлено с начальным байтом значения 7 и хвостовым контрольным полубайтом значения 14 как

0000'0111 0010'0101 0001'0000 1000'1110

Но ожидается, что вы отправите ровно 4 байта, а не эту длинную строку.

Так же, как подсказка: приведенное выше в шестнадцатеричном представлении

0x0725108E

Обратите внимание, что 2510.8 отображается здесь как 25108. Это магия BCD.


Теперь мне потребовалось некоторое время, чтобы понять ваш код LV. Наконец, вы преобразуете это значение 2510,8 в строку "2510.8", а затем извлекаете цифры.

Первая проблема: вы извлекаете строку длины 1 из начала (="2") для z1, строку длины 2 из начала (="25") для z2, строку длины 3 из начала (="251") для z3. .. (="2510") для z4. Вам нужно увеличить начальную позицию и сохранить длину = 1 для метода подстроки.

Во-вторых: вы пытаетесь отформатировать значения как двоичные в строку.

Следующий код преобразует значение b в нужную строку. (Это фрагмент ВП, то есть: Откройте новый ВП и перетащите эту картинку с этого веб-сайта прямо в окно блок-диаграммы!)

введите здесь описание изображения

В деталях:

  • Умножьте b на 10, чтобы получить целое число.
  • Разделите на 10 пять раз в цикле и создайте массив остатков.
    Остатки — это кусочки!
  • изменить направление массива и добавить 14 в качестве последнего кусочка.
  • изменить форму как 2D-массив, поэтому в каждой строке стоят верхний и нижний полубайты
  • цикл по строкам, построение байтов левого и правого столбцов (верхний и нижний полубайт)
  • Вставьте байт 7 в начало нового массива
  • используйте ByteArrayToString, чтобы получить то, что вам нужно отправить на устройство

Примечание:

  • Это одно решение, наверняка есть более быстрые и лучшие. Но это легко.
  • Это решение может преобразовать любое (целое) число в BCD, в то время как C-код очень специфичен для этого единственного варианта использования.
  • U8 в первом цикле необходим, поскольку функция ToString также может преобразовывать 4-байтовые числовые переменные в 4-байтовые строки, а нам нужен 1 байт.
  • Индикатор двоично-десятичных байтов настроен на отображение в шестнадцатеричном формате, это не имеет никакого отношения к значениям
  • Строковый индикатор показывает 4 зашифрованных байта, потому что не все байты являются символами ASCII. Это полностью нормально!
person sweber    schedule 02.11.2019