Convert a GPIB-VXI/C program from NI-488.2 to NI-VISA
For controlling message-based VXI devices through a GPIB-VXI, the biggest difference between a program using NI-488 and one using NI-VISA is in the calls made at the beginning and the end. For register-based devices, the differences are more significant. This topic first discusses the basic changes common to both types of devices, then discusses some of the changes required for register-based programming.
For message-based programming, an NI-488 program would typically call ibdev() with the VXI device's primary and secondary GPIB addresses to get a handle to the specific device. In NI-VISA, a program calls viOpen() with the VXI device's logical address (which is a more natural address because the device is VXI) to get a handle to it. The calls to read and write blocks of data, as well as other IEEE 488 communications (such as reading status bytes and clearing buffers), have a one-to-one mapping between NI-488 and NI-VISA. One difference to be aware of is that when waiting for service requests, a VISA application must first be enabled for that event by using viEnableEvent(). At the end of the application, use viClose() instead of ibonl to close the device handle.
Register-based programming does not have a straightforward mapping. Because register accesses using the GPIB-VXI involve sending requests to the controller itself (using the local command set), NI-488 programs would use ibdev() with the GPIB-VXI controller's primary and secondary GPIB addresses. In NI-VISA, you call viOpen() with the VXI device's logical address—this is the same for both message-based and register-based devices and is a more natural and intuitive API—and VISA handles sending the necessary messages to the controller. For programming the device, the following NI-488 messages and NI-VISA operations are roughly equivalent:
NI-488 | NI-VISA |
"Laddrs?" or "DLAD?" | viFindRsrc() |
"RMentry?" or "DINF?" | viGetAttribute() |
"Cmdr?" | viGetAttribute() with VI_ATTR_CMDR_LA |
"LaSaddr?" | viGetAttribute() with VI_ATTR_GPIB_SECONDARY_ADDR |
"Primary?" | viGetAttribute() with VI_ATTR_GPIB_PRIMARY_ADDR |
"WREG" or "A16" | viOut16() with VI_A16_SPACE |
"RREG?" or "A16?" | viIn16() with VI_A16_SPACE |
"A24" | viOut16() with VI_A24_SPACE |
"A24?" | viIn16() with VI_A24_SPACE |
"SrcTrig" | viAssertTrigger() |
Notice that with the INSTR register access operations viOut16() and viIn16(), you pass a device-relative offset in the specified address space. This is different from the GPIB-VXI's local command set, which accepts absolute addresses. If your application currently uses absolute addressing and you do not want to convert to device-relative offsets, you may consider the MEMACC resource, which accepts absolute addressing. You can use the operations viOut8() and viIn8() to perform 8-bit accesses, which is not a feature supported by the local command set. VISA also defines 32-bit operations and accesses to A32 space, but because these are not implemented by the GPIB-VXI itself, they return errors.
If you have used the DMAmove code instrument, you can now use the viMoveInxx() and viMoveOutxx() operations instead. They make use of the GPIB-VXI's DMA functionality, but require only a single operation call, instead of the multiple calls required to send the command and data blocks and then poll waiting for the operation to complete. Using VISA to move blocks of data also means that you no longer need to load the DMAmove code instrument, as NI-VISA automatically downloads a separate code instrument to handle these and other operations.
In summary, using NI-VISA to program VXI devices controlled by a GPIB-VXI is no different than if they are controlled with a native VXI controller such as an external controller or the VXIpc series. Although porting the code from NI-488 to NI-VISA is not simple in the case of register-based programming, the easier API and the compatibility with native VXI controllers should be worth the change.