Writing 32-Bit Delphi Applications Using NI-488.2 Software
Overview
Borland Delphi (version 2.0), one of the latest visual programming languages, uses Rapid Application Development (RAD) tools. With RAD tools, one can quickly and easily create Windows applications. Delphi is based on Object Pascal and is combined with a native-code compiler. Delphi is capable of accessing dynamic link libraries (DLLs), which makes it easy to interface to NI-488.2M software. This document explains how to access the NI-488.2M DLL from a Delphi application.
Table of Contents
Writing Your NI-488 or NI-488.2 Application
A 32-bit Delphi application can access the NI-488.2M dynamic link library (gpib-32.dll) by using the direct entry functions. This section discusses items you should include in your application along with examples.Exporting Pointers to Status Variables and Function Names
The 32-bit GPIB DLL exports pointers to the global variables and all of the NI-488.2 functions and subroutines. Pointers to the global variables (ibsta, iberr, and ibcntl) are accessible through these exported variables:
int *user_ibsta
int *user_iberr
int *user_ibcntl
Except for the functions ibbna, ibfind, ibrdf, and ibwrtf, all of the NI-488.2 function and subroutine names are exported from the 32-bit GPIB DLL. What this means is that to use direct entry to access a particular function, all you need to do to get a pointer to the exported function is to call GetProcAddress, passing the name of the function as a parameter. The parameters that you use when you invoke the function are identical to those described in Reference 1.
These functions all require an argument that is a name. ibbna requires a board name, ibfind requires a board or device name, and ibrdf and ibwrtf take a file name. Because Windows NT understands both normal (8-bit) and uni-code (16-bit) characters, gpib-32.dll exports both normal and unicode characters. However, under Windows 95 you cannot use 16-bit wide characters. For Windows 95 applications, use the 8-bit ASCII versions named ibbnaA, ibfindA, ibrdfA, and ibwrtfA when calling GetProcAddress. For Windows NT applications, you can use the 16-bit unicode versions named ibbnaW, ibfindW, ibrdfW, and ibwrtfW when calling GetProcAddress.
In addition to pointers to the status variables and a handle to the loaded gpib-32.dll, you must define the direct entry prototypes for the functions that you use in your application. The prototypes for each function exported by gpib-32.dll can be found in Reference 1. For more information on direct entry, refer to the Win32 SDK (Software Development Kit) online help.
Items to Include
In your Win32 Delphi application, you first need to make type declarations for the GPIB global variables. The GPIB globals are declared as functions that return an integer (or Longint for ibcntl). Also included is the calling convention directive, stdcall. Below is an example of how to make the type declaration for the GPIB global variables:
Tibsta = function : integer; stdcall;
Tiberr = function : integer; stdcall;
Tibcntl = function : Longint; stdcall;
In the var section of your application, the AddrIbxxx declarations are used to obtain the addresses of the global variables and the Pibxxx pointer declarations are assigned the AddrIbxxx addresses and from there they can then be dereferenced. Below is an example of how to set them up:
AddrIbsta : Tibsta;
AddrIberr : Tiberr;
AddrIbcntl : Tibcntl;
Pibsta : ^integer;
Piberr : ^integer;
Pibcntl : ^Longint;
The NI-488 calls are declared as functions and NI-488.2 calls are declared as procedures. The declared calls are followed by the list of parameters for that call. The last item in the call declaration is the calling convention directive, stdcall. Include the type declarations for the GPIB functions in the type section of your Pascal unit module. See Reference 1 for the format for the NI-488.2 and NI-488 prototypes. To convert from the C-style parameters (shown in the manual) to Delphi-style parameters, refer to the table below:
C-Style Declaration | Delphi-Style Declaration | Description |
| Addr4882_t num | num : Smallint | Short integer variable passed by value |
| Addr4882_t *list | type AddrList = array[0..31] of Smallint var results : AddrList | Array of short integers |
| char *udname | udname : packed array[0..10] of char | Array of characters passed by reference (e.g., for ibbna and ibfind calls) |
| char *byteBuf | var byteBuf: byte | Unsigned byte variable passed by reference (e.g., for ibrpp and ibrsp calls) |
| int num | num : integer | Integer variable passed by value |
| int *num | var num : integer | Integer variable passed by reference |
| long num | num : longint | Long integer variable passed by value |
| short *results | type ResultsList = array[0..31] of Smallint var results : ResultsList | Array of short integers |
| short *num | var num : Smallint | Short integer variable passed by reference |
| unsigned short num | num : word | Unsigned short integer variable passed by value |
| void *buffer | var buffer | String passed by reference |
Below is an example of how to make a type declaration for the ibdev function:
Tibdev = function (ud:integer;
pad:integer;
sad:integer;
tmo:integer;
eot:integer;
eos:integer) : integer; stdcall;
Below is an example of how to make a type declaration for the SendIFC procedure:
TSendIFC = procedure (boardID: integer); stdcall;
Below is an example of how to declare the calls in the var section:
ibdev : Tibdev;
SendIFC : TSendIFC;
You also need a handle to the GPIB library. Below is an example of how to declare it in the var section of your application:
Gpib32Lib : THandle;
In the const section of your application, you can set up mnemonics for the Status Word Conditions and Error Codes as found in the Appendixes of Reference 1. These constants can be used in your application to help check which bits are set in the GPIB global variables, ibsta and iberr. Below is an example of how to declare them:
const
(* GPIB Status Word Conditions. *)
ERR = $8000; (* Error detected *)
TIMO = $4000; (* Timeout *)
EEND = $2000; (* EOI or EOS detected *)
SRQI = $1000; (* SRQ detected by CIC *)
RQS = $800; (* Device needs service *)
SPOLL = $400; (* Board has been serially polled *)
EVENT = $200; (* An event has occurred *)
CMPL = $100; (* I/O completed *)
LOK = $80; (* Local lockout state *)
REM = $40; (* Remote state *)
CIC = $20; (* Controller-in-Charge *)
ATN = $10; (* Attention asserted *)
TACS = $8; (* Talker active *)
LACS = $4; (* Listener active *)
DTAS = $2; (* Device trigger state *)
DCAS = $1; (* Device clear state *)
(* Error messages returned in global variable IBERR: *)
EDVR = 0;(* System error *)
ECIC = 1;(* Function requires GPIB board to be CIC *)
ENOL = 2;(* Write function detected no Listeners *)
EADR = 3;(* Interface board not addressed correctly *)
EARG = 4;(* Invalid argument to function call *)
ESAC = 5;(* Function requires GPIB board to be SAC *)
EABO = 6;(* I/O operation aborted *)
ENEB = 7;(* Non-existent interface board *)
EDMA = 8;(* Error performing DMA *)
EOIP = 10;(* I/O operation started before previous *)
(* operation completed *)
ECAP = 11;(* No capability for intended operation *)
EFSO = 12;(* File system operation error *)
EBUS = 14;(* Command error during device call *)
ESTB = 15;(* Serial poll status byte lost *)
ESRQ = 16;(* SRQ remains asserted *)
ETAB = 20;(* The return buffer is full *)
ELCK = 21;(* Address or board is locked *)
Loading the GPIB-32.DLL Library
In your Win32 application, you need to load the GPIB library (gpib-32.dll). The following code fragment illustrates how to call the LoadLibrary function and check for an error:
Gpib32Lib := LoadLibrary('GPIB-32.DLL');
If Gpib32Lib = 0 Then
begin
(* Report an error here. *)
end;
Getting the Addresses
Next, your Win32 application needs to use GetProcAddress to get the addresses of the global status variables and functions you need to use. The following code fragment illustrates how to get the addresses of the pointers to the status variables and any functions your application needs to use:
@AddrIbsta := GetProcAddress(Gpib32Lib, 'user_ibsta');
@AddrIberr := GetProcAddress(Gpib32Lib, 'user_iberr');
@AddrIbcntl := GetProcAddress(Gpib32Lib, 'user_ibcntl');
Pibsta := @AddrIbsta;
Piberr := @AddrIberr;
Pibcntl := @AddrIbcntl;
(* NI-488 calls *)
@ibdev := GetProcAddress(Gpib32Lib, 'ibdev');
@ibonl := GetProcAddress(Gpib32Lib, 'ibonl');
(* NI-488.2 call *)
@SendIFC := GetProcAddress(Gpib32Lib, 'SendIFC');
If GetProcAddress fails, it returns a NIL pointer. The following code fragment illustrates how to verify that none of the calls to GetProcAddress failed:
If (@AddrIbsta = NIL) or
(@AddrIberr = NIL) or
(@AddrIbcntl = NIL) or
(@ibdev = NIL) or
(@ibonl = NIL) then
begin
(* Report an error. *)
FreeLibrary(Gpib32Lib); (* Free the library. *)
end;
Accessing the GPIB Calls and Variables
The code below illustrates how to call a function or a procedure and access the status variable from within your application:
dev := ibdev(0, 1, 0, 13, 1, 0);
if (Pibsta^ and ERR) <> 0 then
gpiberr('ibdev Error');
SendIFC(0);
if (Pibsta^ and ERR) <> 0 then
gpiberr('SendIFC Error');
Freeing the Library
Before exiting your application, you need to free gpib-32.dll with the following command:
FreeLibrary(Gpib32Lib);
Sample Programs
The Download section of our GPIB Web site includes two sample programs that illustrate how to make direct entry calls to interface to a multimeter. Please see the related link below.
See Also:
GPIB Web site
Reader Comments | Submit a comment »
Delphi
This 32 bit app.. was for me the BIGGEST help for delphi 4 all my test &
calibration app.. are in delphi, I am converting my
soft.. to math the NI
GPIB card,
Agilent (HP) with 82350 card, do not support
delphi app.. You
made the right decision by
supporting DELPHI, THANKS AGAIN
Michel Fyfe
Nortel networks
- Feb 25, 2002
Legal
This tutorial (this "tutorial") was developed by National Instruments ("NI"). Although technical support of this tutorial may be made available by National Instruments, the content in this tutorial may not be completely tested and verified, and NI does not guarantee its quality in any way or that NI will continue to support this content with each new revision of related products and drivers. THIS TUTORIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND AND SUBJECT TO CERTAIN RESTRICTIONS AS MORE SPECIFICALLY SET FORTH IN NI.COM'S TERMS OF USE (http://ni.com/legal/termsofuse/unitedstates/us/).
