简体   繁体   English

如何使用 LabVIEW 将打包的 BCD 数字写入旧仪器(Varian FR41 Gaussmeter)?

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

I am currently trying to communicate with an old instrument that uses packed BCD numbers only (it's a Varian FR41 Controller Gaussmeter if anyone is familiar).我目前正在尝试与仅使用打包 BCD 数字的旧仪器进行通信(如果有人熟悉,它是 Varian FR41 Controller 高斯计)。 I am using LabVIEW to replicate some old C code that output the BCD code.我正在使用 LabVIEW 复制一些旧的 C 代码,即 output BCD 代码。 Below is the C script.下面是 C 脚本。 What it is doing is some simple arithmetic to generate integers that are exported to the instrument through the IEEE port using %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);
}

I have generated a.VI that generates the same numbers b1,b2,b3 and puts them into a string of packed BCD numbers.我生成了一个生成相同数字b1,b2,b3的 VI,并将它们放入一串打包的 BCD 数字中。 Using the input variables HV,magconst,mass above, the output should be 2510.8 gauss.使用上面的输入变量HV,magconst,mass ,output 应该是2510.8高斯。 and b1,b2,b3 are 142,37,16 respectively. b1,b2,b3分别为142,37,16

Now on to what the Varian Gaussmeter wants.现在看看瓦里安高斯计想要什么。 This is the text that describes how the instrument receives information (not all of this is useful, but I copy it for the sake of completeness).这是描述仪器如何接收信息的文本(并非所有这些都是有用的,但为了完整起见,我复制了它)。 I'm also attaching an image of the schematic that shows the BCD format.我还附上了一张显示 BCD 格式的示意图。 手册中的 BCD 格式

Data are transmitted to the FR-41 as a sequence of three 8 bit bytes.数据以三个 8 位字节的序列传输到 FR-41。 Each byte is divided into two half bytes, hi and lo, which may contain BCD numbers only.每个字节分为两个半字节,hi 和 lo,它们可能只包含 BCD 数字。 When auxiliary output port is used a fourth byte (any binary number) is added to the beginning of the sequence.当使用辅助 output 端口时,将第四个字节(任何二进制数)添加到序列的开头。 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.发送的最后一个字符在高字节位置包含新高斯设置的最低有效位 (LSD),在低字节中包含加载控制非 BCD 字符 (bin 14),它被解释为用新数据加载所有寄存器。 The one bit of the lo byte controls the 10 kGauss overrange when used. lo 字节的一位控制使用时的 10 kGauss 超量程。 no change of setting occurs until the control word is received.在接收到控制字之前不会更改设置。

So, if I'm understanding this correctly in the C code above, the first byte added (aux output port thing) seems to be 7, which should be 0000 0111 in BCD.因此,如果我在上面的C代码中正确理解这一点,则添加的第一个字节(辅助 output 端口事物)似乎是 7,在 BCD 中应该是0000 0111 The following bytes, to write 2510.8, should be 0010 0101 0001 0000 1000 followed by 1110 (for the bin 14 control word).以下字节,要写入 2510.8,应该是0010 0101 0001 0000 1000后跟1110 (用于 bin 14 控制字)。

Here's what I have done.这就是我所做的。 Using the attached.VI, I can reproduce the 32 bit BCD string that I expect it should be.使用附加的.VI,我可以重现我期望的 32 位 BCD 字符串。 I'm sending this to the GPIB Send Message VI in LabVIEW (I've also tried using VISA Write, but it does the exact same thing across all tests as far as I can see).我将它发送到 LabVIEW 中的 GPIB Send Message VI(我也尝试过使用 VISA Write,但据我所知,它在所有测试中执行完全相同的操作)。 However, the instrument doesn't register anything happening.然而,仪器没有记录任何发生的事情。

The interesting thing is that when I send the instrument the information as a %f string, of floating points, so, 7.0000142.00037.00016.000 , the instrument registers something happening and the tens and hundreds places change.有趣的是,当我将信息作为%f字符串(浮点数)发送给仪器时,因此, 7.0000142.00037.00016.000 ,仪器记录了发生的事情,并且数十位和数百位发生了变化。 So, if I send 42 as a floating point, the instrument will go to X4X2.X gauss setting.因此,如果我发送42作为浮点数,仪器会将 go 设置为 X4X2.X 高斯设置。 If I put 142 it will do the same thing.如果我输入142它会做同样的事情。 If I put 17 it will go to X1X7.X setting.如果我放17它将 go 到 X1X7.X 设置。 If I send it 17 then 25 it will only take the first one.如果我发送它17然后25它只会拿第一个。

My thought is that something in the GPIB Send or VISA Write is taking my string of BCD numbers and sending them out as something else, but I can't figure out what I could be doing wrong.我的想法是 GPIB Send 或 VISA Write 中的某些内容正在获取我的 BCD 数字字符串并将它们作为其他内容发送出去,但我无法弄清楚我可能做错了什么。 Any help or tests would be much appreciated;任何帮助或测试将不胜感激; I've been struggling with this for weeks now to no avail.我已经为此苦苦挣扎了几个星期,但无济于事。 用于重现上面复制的 C 脚本的 VI

As you wrote, the value 2510.8 should be send with a leading byte of value 7 and a tailing control nibble of value 14 as正如您所写,值 2510.8 应该使用值 7 的前导字节和值 14 的尾随控制半字节发送为

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

But you are expected to send exactly 4 Bytes, not this long string.但是您应该准确发送 4 个字节,而不是这个长字符串。

Just as hint: The above in hexadecimal representation is正如提示:上面的十六进制表示是

0x0725108E

Note how the 2510.8 appears as 25108 here.请注意 2510.8 在此处如何显示为 25108。 That's the magic of BCD.这就是 BCD 的魔力。


Now, it took me a while to understand your LV code.现在,我花了一段时间才理解你的 LV 代码。 Finally, you convert that value of 2510.8 into a string "2510.8" , and then extract the digits.最后,将该值 2510.8 转换为字符串"2510.8" ,然后提取数字。

First problem: You extract a string of length 1 from the beginning (= "2" ) for z1 , a string of length 2 from the beginning (= "25" ) for z2 , a string of length 3 from the beginning (= "251" ) for z3 ... (= "2510" ) for z4 .第一个问题:您从z1的开头提取长度为 1 的字符串 (= "2" ),从z2的开头提取长度为 2 的字符串 (= "25" ),从开头提取长度为 3 的字符串 (= "251" ) 对于z3 ... (= "2510" ) 对于z4 You need to increment the starting position, and keep the length =1 for the substring method.您需要增加起始 position,并保持 substring 方法的长度 = 1。

Second: You try to format the values as binary into a string.第二:您尝试将值作为二进制格式格式化为字符串。

The following code converts value b into the desired string.以下代码将值 b 转换为所需的字符串。 (It is a VI-snippet, that is: Open a new VI, and drag this picture from this website directly into the block diagramm window!) (它是一个VI-snippet,即:打开一个新的VI,把这个网站上的图片直接拖到程序框图窗口中!)

在此处输入图像描述

In detail:详细地:

  • Multiply b by 10 to make it integer将 b 乘以 10 使其成为 integer
  • Divide by 10 five times in a loop, and create an array of the remainders.在一个循环中除以 10 五次,并创建一个余数数组。
    The remainders are the nibbles!剩下的就是零嘴了!
  • revert the direction of the array, and append a 14 as last nibble.恢复数组的方向,并将 append a 14作为最后一个半字节。
  • reshape as 2D array, so in each row stand the upper and the lower nibble重塑为二维数组,因此在每一行中都有上半字节和下半字节
  • loop over rows, build bytes of the left and right colums (upper and lower nibble)循环遍历行,构建左右列的字节(上半字节和下半字节)
  • Insert a byte 7 at the beginning of the new array在新数组的开头插入一个字节7
  • use ByteArrayToString to get what you need to send to the device使用 ByteArrayToString 获取您需要发送到设备的内容

Note:笔记:

  • This is one solution, there are for sure faster and better ones.这是一种解决方案,肯定有更快更好的解决方案。 But this is easy.但这很容易。
  • This solution can convert any (integer) number to BCD, while the C-code is very specific to this single use case该解决方案可以将任何(整数)数字转换为 BCD,而 C 代码非常特定于这个单一用例
  • The U8 in the first loop is necessary, since the ToString function can also convert 4byte numerical variables to 4byte strings, but we need 1byte.第一个循环中的 U8 是必要的,因为 ToString function 也可以将 4byte 数值变量转换为 4byte 字符串,但我们需要 1byte。
  • The BCD Bytes indicator has been set to display as HEX, this has nothing to do with the values BCD Bytes 指标已设置为显示为 HEX,这与值无关
  • The string indicator shows 4 cryptic bytes, because not all bytes are ASCII characters.字符串指示器显示 4 个神秘字节,因为并非所有字节都是 ASCII 字符。 This is fully OK!这完全没问题!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM