1

我目前正在尝试与仅使用打包 BCD 数字的旧仪器进行通信(如果有人熟悉,它是 Varian FR41 控制器高斯计)。我正在使用 LabVIEW 来复制一些输出 BCD 代码的旧 C 代码。下面是 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高斯。和b1,b2,b3分别是142,37,16

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

数据以三个 8 位字节的序列传输到 FR-41。每个字节分为两个半字节,hi 和 lo,它们可能只包含 BCD 数字。当使用辅助输出端口时,将第四个字节(任何二进制数)添加到序列的开头。发送的最后一个字符在高字节位置包含新高斯设置的最低有效位 (LSD),在低字节中包含加载控制非 BCD 字符 (bin 14),它被解释为用新数据加载所有寄存器。lo 字节的一位控制使用时的 10 kGauss 超量程。在接收到控制字之前不会更改设置。

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

这就是我所做的。使用附加的 .VI,我可以重现我期望的 32 位 BCD 字符串。我将它发送到 LabVIEW 中的 GPIB Send Message VI(我也尝试过使用 VISA Write,但据我所知,它在所有测试中执行完全相同的操作)。然而,仪器没有记录任何发生的事情。

有趣的是,当我将信息作为%f浮点数的字符串发送给仪器时7.0000142.00037.00016.000,仪器会记录正在发生的事情,并且数十位和数百位发生了变化。因此,如果我42以浮点形式发送,仪器将进入 X4X2.X 高斯设置。如果我把142它做同样的事情。如果我把17它转到 X1X7.X 设置。如果我发送它,17那么25它只会占用第一个。

我的想法是 GPIB Send 或 VISA Write 中的某些内容正在获取我的 BCD 数字字符串并将它们作为其他内容发送出去,但我无法弄清楚我可能做错了什么。任何帮助或测试将不胜感激;我已经为此苦苦挣扎了几个星期,但无济于事。用于重现上面复制的 C 脚本的 VI

4

1 回答 1

3

正如您所写,值 2510.8 应该使用值 7 的前导字节和值 14 的尾随控制半字节发送为

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

但是您应该准确发送 4 个字节,而不是这个长字符串。

正如提示:上面的十六进制表示是

0x0725108E

请注意 2510.8 在此处如何显示为 25108。这就是 BCD 的魔力。


现在,我花了一段时间才理解你的 LV 代码。最后,将该值 2510.8 转换为 string "2510.8",然后提取数字。

第一个问题:从开头 (= ) 提取长度为 1 的字符串 for ,从开头 (= "2")提取长度为z12 的字符串 for ,从开头 (= "25")提取长度为z23 的字符串... (= ) for . 您需要增加起始位置,并为 substring 方法保持长度 =1。"251"z3"2510"z4

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

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

在此处输入图像描述

详细地:

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

笔记:

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