如何使用 LabVIEW 将打包的 BCD 码写入旧仪器(Varian FR41 高斯计)?

How can I write packed BCD numbers to an old instrument (Varian FR41 Gaussmeter) with LabVIEW?

我目前正在尝试与仅使用打包 BCD 码的旧仪器进行通信(如果有人熟悉的话,它是 Varian FR41 控制器高斯计)。我正在使用 LabVIEW 复制一些输出 BCD 代码的旧 C 代码。下面是 C 脚本。它正在做的是一些简单的算法来生成整数,这些整数使用 %c 通过 IEEE 端口导出到仪器。

#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 高斯。和 b1,b2,b3 分别是 142,37,16

现在谈谈 Varian 高斯计想要什么。这是描述仪器如何接收信息的文本(并非所有这些都有用,但为了完整起见,我将其复制)。我还附上了一张显示 BCD 格式的示意图。

Data are transmitted to the FR-41 as a sequence of three 8 bit bytes. Each byte is divided into two half bytes, hi and lo, which may contain BCD numbers only. When auxiliary output port is used a fourth byte (any binary number) is added to the beginning of the sequence. The last character sent contains the least significant digit (LSD) of the new Gauss setting in the hi byte location and a load control NON BCD character, (bin 14) in the lo byte which is interpreted to load all registers with the new data. The one bit of the lo byte controls the 10 kGauss overrange when used. no change of setting occurs until the control word is received.

所以,如果我在上面的 C 代码中理解正确,添加的第一个字节(aux 输出端口)似乎是 7,在 BCD 中应该是 0000 0111。接下来的字节,要写入 2510.8,应该是 0010 0101 0001 0000 1000 后跟 1110(对于 bin 14 控制字)。

这是我所做的。使用附带的 .VI,我可以重现我期望的 32 位 BCD 字符串。我将它发送到 LabVIEW 中的 GPIB 发送消息 VI(我也尝试过使用 VISA Write,但据我所知,它在所有测试中都做同样的事情)。然而,该仪器没有记录任何发生的事情。

有趣的是,当我将信息作为 %f 浮点字符串发送给仪器时,因此 7.0000142.00037.00016.000,仪器记录了一些发生的事情,十位和百位发生了变化.所以,如果我发送 42 作为浮点数,仪器将进入 X4X2.X 高斯设置。如果我输入 142 它会做同样的事情。如果我输入 17 它将转到 X1X7.X 设置。如果我发送 17 然后 25 它只会接受第一个。

我的想法是 GPIB Send 或 VISA Write 中的某些东西正在获取我的 BCD 数字串并将它们作为其他东西发送出去,但我无法弄清楚我可能做错了什么。任何帮助或测试将不胜感激;我已经为此苦苦挣扎了数周,但无济于事。

如您所写,发送值 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") for z3... (="2510") for z4。您需要增加起始位置,并为 substring 方法保持长度 =1。

其次:您尝试将二进制值格式化为字符串。

以下代码将值 b 转换为所需的字符串。 (是一个VI-snippet,就是:打开一个新的VI,把这张图片从这个网站直接拖到程序框图里window!)

详细:

  • 将 b 乘以 10 得到整数
  • 在循环中五次除以 10,并创建一个余数数组。
    剩下的就是半字节了!
  • 反转数组的方向,并附加一个 14 作为最后一个半字节。
  • 整形为二维数组,所以每一行都有上下半字节
  • 遍历行,构建左右列(上下半字节)的字节
  • 在新数组的开头插入一个字节7
  • 使用 ByteArrayToString 获取您需要发送到设备的内容

注:

  • 这是一种解决方案,肯定还有更快更好的解决方案。但这很容易。
  • 此解决方案可以将任何(整数)数字转换为 BCD,而 C 代码非常特定于此单个用例
  • 第一个循环中的U8是必须的,因为ToString函数也可以将4byte的数值变量转换为4byte的字符串,但是我们需要1byte。
  • BCD 字节指标已设置为显示为 HEX,这与数值无关
  • 字符串指示器显示 4 个神秘字节,因为并非所有字节都是 ASCII 字符。这完全可以!