Java中,使用JNA调用Visa32.dll,控制频谱仪~~
C:\Program Files\Agilent\IO Libraries Suite\ 有visa.chm,是方法和属性的说明。
首先,难倒在viOpen方法上。连不上频谱仪,什么都白搭啊~~
在visa.chm中,viOpen的格式如下:
viOpen(ViSession sesn, ViRsrc rsrcName, ViAccessMode accessMode, ViUInt32 timeout, ViPSession vi);
在 C:\Program Files\IVI Foundation\VISA\WinNT\include visa.h visatype.h 两个文件中,可以查看类型定义。visa.chm中也有说明。
ViSession、ViPSession,ViAccessMode 和ViUInt32,其实都是unsigned long ViRsrc其实是char
所以,初始JNA代码如下:
package jna;
import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.ptr.LongByReference;
public class InstrumentWrong {
public interface VISA32 extends Library {
// VISA32 INSTANCE = (VISA32) Native.loadLibrary("VISA32", // VISA32.class); VISA32 INSTANCE = (VISA32) Native.loadLibrary( "C:\\WINDOWS\\system32\\VISA32.dll", VISA32.class);
public static final long VI_NULL = 0; public static final long VI_SUCCESS = 0;
public int viOpenDefaultRM(LongByReference session);
public int viOpen(long viSession, String rsrcName, long accessMode, long timeout, LongByReference session);
public int viClose(long vi); }
LongByReference defaultSession; LongByReference vipSession;
public boolean open(String deviceType, String ip) { VISA32 visa32 = VISA32.INSTANCE;
defaultSession = new LongByReference(0); int result = visa32.viOpenDefaultRM(defaultSession); if (result != VISA32.VI_SUCCESS) { return false; }
vipSession = new LongByReference(0); String cmd = "TCPIP0::<ip>::inst0::INSTR".replace("<ip>", ip); result = visa32.viOpen(defaultSession.getValue(), cmd, VISA32.VI_NULL, VISA32.VI_NULL, vipSession); if (result != VISA32.VI_SUCCESS) { System.out.println(result); return false; } return true; }
/** * 关闭设备. * * @return 成功返回true,失败返回false */ public boolean close() { int result = VISA32.INSTANCE.viClose(vipSession.getValue()); if (result != VISA32.VI_SUCCESS) { return false; }
result = VISA32.INSTANCE.viClose(defaultSession.getValue()); if (result != VISA32.VI_SUCCESS) { return false; }
return true; }
/** * @param args */ public static void main(String[] args) { InstrumentWrong device = new InstrumentWrong(); boolean isOpen = device.open("xxx", "192.168.1.10"); if (!isOpen) { System.out.println("open failed."); return; }
device.close();
}
}
运行,始终报错: -1073807342 open failed.
在visa.h中搜错误号,可知定义是VI_ERROR_INV_RSRC_NAME。 是资源名字不正确~~~
搜了N久,以为是编码的问题,试过传递byte[]什么的,依然报此错误。 烦恼N久~~~
后经牛人指定,恍然大悟~~~
JNA的文档说明在此: http://jna.java.net/javadoc/overview-summary.html#buffers -------------------------- C Type Native Representation Java Type long long, __int64 64-bit integer long long platform-dependent (32- or 64-bit integer) NativeLong -----------------------------
原来VISA中是32位的long,所以java中应该用NativeLong,而不是long~~~
修改后代码如下:
package jna;
import com.sun.jna.Library; import com.sun.jna.Memory; import com.sun.jna.Native; import com.sun.jna.NativeLong; import com.sun.jna.ptr.LongByReference;
public class InstrumentRight {
public interface VISA32 extends Library {
// VISA32 INSTANCE = (VISA32) Native.loadLibrary("VISA32", // VISA32.class); VISA32 INSTANCE = (VISA32) Native.loadLibrary( "C:\\WINDOWS\\system32\\VISA32.dll", VISA32.class);
public static final long VI_NULL = 0; public static final long VI_SUCCESS = 0;
public int viOpenDefaultRM(LongByReference session);
public int viOpen(NativeLong viSession, String rsrcName, NativeLong accessMode, NativeLong timeout, LongByReference session);
public int viClose(NativeLong vi);
public int viScanf(NativeLong vi, String readFmt, Object... args);
public int viPrintf(NativeLong vi, String writeFmt, Object... args); }
LongByReference defaultSession; LongByReference vipSession;
public boolean open(String deviceType, String ip) { VISA32 visa32 = VISA32.INSTANCE;
defaultSession = new LongByReference(0); int result = visa32.viOpenDefaultRM(defaultSession); if (result != VISA32.VI_SUCCESS) { return false; }
vipSession = new LongByReference(0); String cmd = "TCPIP0::<ip>::inst0::INSTR".replace("<ip>", ip); NativeLong a = new NativeLong(defaultSession.getValue()); NativeLong b = new NativeLong(0); result = visa32.viOpen(a, cmd, b, b, vipSession); if (result != VISA32.VI_SUCCESS) { System.out.println(result); return false; } return true; }
/** * 关闭设备. * * @return 成功返回true,失败返回false */ public boolean close() { NativeLong a = new NativeLong(vipSession.getValue()); int result = VISA32.INSTANCE.viClose(a); if (result != VISA32.VI_SUCCESS) { System.out.println(result); return false; }
NativeLong b = new NativeLong(defaultSession.getValue()); result = VISA32.INSTANCE.viClose(b); if (result != VISA32.VI_SUCCESS) { System.out.println(result); return false; }
return true; }
public boolean writeCmd(String cmdStr) { NativeLong a = new NativeLong(vipSession.getValue()); int result = VISA32.INSTANCE.viPrintf(a, "%s\n", cmdStr); if (result != VISA32.VI_SUCCESS) { System.out.println(result); return false; } return true; }
public String readResult() { NativeLong a = new NativeLong(vipSession.getValue()); Memory mem = new Memory(200); int result = VISA32.INSTANCE.viScanf(a, "%t", mem); if (result != VISA32.VI_SUCCESS) { System.out.println(result); return null; } return mem.getString(0); }
/** * @param args */ public static void main(String[] args) { InstrumentRight device = new InstrumentRight(); boolean isOpen = device.open("xxx", "192.168.1.10"); if (!isOpen) { System.out.println("open failed."); return; }
// 查询设备名称 device.writeCmd("*IDN?");
// 读取返回值 String s = device.readResult(); System.out.println(s);
device.close();
}
}
执行,得到设备名称,OK啦~~哈 -------------------------- 好像直接用int也可以~~~
|