Computer Laboratory

Matlab provides an instrument control toolbox to drive GPIB devices under Windows. However this doesn't seem to work under Linux (Matlab 7.2.0.294). It appears, while there's a driver for National Instrument GPIB devices under Linux, the Matlab-GPIB interface isn't implemented.

Here we present a simple way to send GPIB commands from Linux.

We make us of NI's Linux driver. To interface this to Matlab we create a C-language program which uses Matlab's MEX external interface. The NI GPIB driver, when installed, can be linked to a C program using -lgpibapi.

Receive function

A Matlab function resultString=ibrd(gpibPrimaryAddress,bytesToRead) to receive bytes as Matlab strings from the GPIB device is presented below:

#include "ni488.h"
#include <stdlib.h>
#include <stdio.h>
#include "mex.h"

int i;
int Device = 0;                   /* Device unit descriptor                  */
int BoardIndex = 0;               /* Interface Index (GPIB0=0,GPIB1=1,etc.)  */

#define RESPONSE_LENGTH 100       /* default length of maximum response we can read from the GPIB device */

/* this is the entry point called from Matlab */
/* resultString = ibrd(gpibPrimaryAddress) */
/* resultString = ibrd(gpibPrimaryAddress,bytesToRead) */
void mexFunction(
    int nlhs, mxArray *plhs,
    int nrhs, const mxArray *prhs)
{    
   int   PrimaryAddress = 2;      /* Primary address of the device           */
   int   SecondaryAddress = 0;    /* Secondary address of the device         */
   char  Buffer101;             /* Read buffer       */
   int   readLength=0;                                
   
  int mrows, ncols;
   char *input_buf, *output_buf;
  int   buflen,status;
    
  /* Check for proper number of arguments. */
  if (nrhs != 1 && nrhs!=2) {
    mexErrMsgTxt("One or two inputs required.");
  }
  
  /* The first input must be an integer.*/
  mrows = mxGetM(prhs0);
  ncols = mxGetN(prhs0);
  if (!mxIsDouble(prhs0) || mxIsComplex(prhs0) ||
      !(mrows == 1 && ncols == 1)) {
    mexErrMsgTxt("Input must be a single integer");
  }  

 /* read the address parameter from the supplied Matlab matrix */
 PrimaryAddress = (int) *(mxGetPr(prhs0));
 
 /* if we're supplied with a number of bytes to read, use that instead of
  * our default of RESPONSE_LENGTH */
 if (nrhs>1)
 {
  /* The input must be a noncomplex scalar double.*/
  mrows = mxGetM(prhs1);
  ncols = mxGetN(prhs1);
  if (!mxIsDouble(prhs1) || mxIsComplex(prhs1) ||
      !(mrows <= 1 && ncols <= 1)) {
    mexErrMsgTxt("Input must be a noncomplex scalar double.");
  }
   /* if it's a null matrix, ignore it */
   if (mrows == 0 || ncols == 0) {
    readLength=0;
  }
  else
  {
     readLength = (int) *(mxGetPr(prhs1));
  }
 }
 else
     readLength=0;
 
 if (readLength==0)
     readLength=RESPONSE_LENGTH;
 
  /* Allocate memory for output string. */
  output_buf = mxCalloc(readLength, sizeof(char));

/*****************************************************************************
 * GPIB Initialization - Done only once at the beginning of your application.
 *****************************************************************************/

   Device = ibdev(                /* Create a unit descriptor handle         */
         BoardIndex,              /* Board Index (GPIB0 = 0, GPIB1 = 1, ...) */
         PrimaryAddress,          /* Device primary address                  */
         SecondaryAddress,        /* Device secondary address                */
         T10s,                    /* Timeout setting (T10s = 10 seconds)     */
         1,                       /* Assert EOI line at end of write         */
         0);                      /* EOS termination mode                    */
   if (ibsta & ERR) {             /* Check for GPIB Error                    */
      mexErrMsgTxt("ibdev Error"); 
   }

  
/*****************************************************************************
 * Main Application Body - Write the majority of your GPIB code here.
 *****************************************************************************/

   ibrd(Device, output_buf, readLength);     /* Read bytes from the device */    
     if (ibsta & ERR) {
        mexErrMsgTxt("ibrd Error");	
        }
     output_bufibcntl = '\0';         /* Null terminate the ASCII string         */

   ibonl(Device, 0);              /* Take the device offline                 */
   if (ibsta & ERR) {
      mexErrMsgTxt("ibonl Error");	
   }

 /* return a pointer to the result string to Matlab */
 plhs0 = mxCreateString(output_buf);
}

Send function

...and a send function ibwrt(gpibAddress,stringToSend):

#include "ni488.h"
#include <stdlib.h>
#include <stdio.h>
#include "mex.h"

int i;
int Device = 0;                   /* Device unit descriptor                  */
int BoardIndex = 0;               /* Interface Index (GPIB0=0,GPIB1=1,etc.)  */
	
/* ibwrt(gpibPrimaryAddress,stringToSend) */	
void mexFunction(
    int nlhs, mxArray *plhs,
    int nrhs, const mxArray *prhs)
{    
   int   PrimaryAddress;      /* Primary address of the device           */
   int   SecondaryAddress = 0;    /* Secondary address of the device         */
   
  int mrows, ncols;
   char *input_buf, *output_buf;
  int   buflen,status;
  
  /* Check for proper number of arguments. */
  if (nrhs != 2) {
    mexErrMsgTxt("2 inputs required.");
  }
  
  /* The input 0 must be a noncomplex scalar double.*/
  mrows = mxGetM(prhs0);
  ncols = mxGetN(prhs0);
  if (!mxIsDouble(prhs0) || mxIsComplex(prhs0) ||
      !(mrows == 1 && ncols == 1)) {
    mexErrMsgTxt("Input must be a noncomplex scalar double.");
  }

  /* Assign pointers to each input and output. */
  PrimaryAddress = (int) *(mxGetPr(prhs0));
  /*printf("PrimaryAddress = %d\n",PrimaryAddress);*/
  
  /* Input 1 must be a string. */
  if (mxIsChar(prhs1) != 1)
    mexErrMsgTxt("Input must be a string.");

  /* Input 1 must be a row vector. */
  if (mxGetM(prhs1) != 1)
    mexErrMsgTxt("Input must be a row vector.");
    
  /* Get the length of the input string. */
  buflen = (mxGetM(prhs1) * mxGetN(prhs1)) + 1;

  /* Allocate memory for input and output strings. */
  input_buf = mxCalloc(buflen, sizeof(char));

  /* Copy the string data from prhs0 into a C string 
   * input_buf. */
  status = mxGetString(prhs1, input_buf, buflen);
  if (status != 0) 
    mexWarnMsgTxt("Not enough space. String is truncated.");

/*****************************************************************************
 * Initialization - Done only once at the beginning of your application.
 *****************************************************************************/

   Device = ibdev(                /* Create a unit descriptor handle         */
         BoardIndex,              /* Board Index (GPIB0 = 0, GPIB1 = 1, ...) */
         PrimaryAddress,          /* Device primary address                  */
         SecondaryAddress,        /* Device secondary address                */
         T10s,                    /* Timeout setting (T10s = 10 seconds)     */
         1,                       /* Assert EOI line at end of write         */
         0);                      /* EOS termination mode                    */
   if (ibsta & ERR) {             /* Check for GPIB Error                    */
      mexErrMsgTxt("ibdev Error"); 
   }

/*****************************************************************************
 * Main Application Body - Write the majority of your GPIB code here.
 *****************************************************************************/

   ibwrt(Device, input_buf, buflen-1);     /* Send the command   */
   if (ibsta & ERR) {
      mexErrMsgTxt("ibwrt Error");
   }

   ibonl(Device, 0);              /* Take the device offline                 */
   if (ibsta & ERR) {
      mexErrMsgTxt("ibonl Error");	
   }

}

These need to be compiled from within Matlab - you need GCC and the GPIB library installed. To compile, issue:

>> mex -lgpibapi ibwrt.c
>> mex -lgpibapi ibrd.c

then you can call the functions as in this example to access GPIB device 2:

>> ibwrt(2,'xsetup0');
>> ibwrt(2,'xr');
>> response=ibrd(2)

response =

XM0000334

>> ibwrt(2,'xr');
>> response=ibrd(2,4)

response =

XM00

>> response=ibrd(2,5)

response =

00334

>>

It would be fairly straightforward for these functions to pass through another parameter to select the secondary address of the device.