/**************************************************************************/ /* Asynchronous I/O Completion Example */ /* */ /* This example shows how to use an asynchronous event handling function */ /* that is called when an asynchronous input/output operation completes. */ /* Compare this to viRead and viWrite which block the application until */ /* either the call returns successfully or a timeout occurs. Read and */ /* write operations can be quite slow sometimes, so these asynchronous */ /* operations will allow you processor to perform other tasks. */ /* The code uses VISA functions and sets a flag in the callback upon */ /* completion of an asynchronous read from a GPIB device to break out of */ /* an otherwise infinite loop. The flow of the code is as follows: */ /* */ /* Open A Session To The VISA Resource Manager */ /* Open A Session To A GPIB Device */ /* Install A Handler For Asynchronous IO Completion Events */ /* Enable Asynchronous IO Completion Events */ /* Write A Command To The Instrument */ /* Call The Asynchronous Read Command */ /* Start A Loop That Can Only Be Broken By A Handler Flag Or Timeout */ /* Print Out The Returned Data */ /* Close The Instrument Session */ /* Close The Resource Manager Session */ /**************************************************************************/ #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) /* Functions like strcpy are technically not secure because they do */ /* not contain a 'length'. But we disable this warning for the VISA */ /* examples since we never copy more than the actual buffer size. */ #define _CRT_SECURE_NO_DEPRECATE #endif #include #include #include #include "visa.h" /* Prototype for the event handler for asynchronous i/o completion */ ViStatus _VI_FUNCH AsyncHandler(ViSession vi, ViEventType etype, ViEvent event, ViAddr userHandle); #define READ_BUFFER_SIZE 4096 static ViJobId job; static unsigned char data[READ_BUFFER_SIZE]; static ViAddr uhandle; static ViStatus status, StatusSession; static ViSession inst, Sessionparam; static ViEventType EventTypeparam; static ViAddr Addressparam; static ViUInt32 BytesToWrite; static ViSession defaultRM; static ViUInt32 rcount, RdCount; static volatile ViBoolean stopflag = VI_FALSE; static int letter; static char stringinput[256]; /* * The handler function. The instrument session, the type of event, and a * handle to the event are passed to the function along with a user handle * which is basically a label that could be used to reference the handler. * The only thing done in the handler is to set a flag that allows the * program to finish. Always return VI_SUCCESS from your handler. */ ViStatus _VI_FUNCH AsyncHandler(ViSession vi, ViEventType etype, ViEvent event, ViAddr userHandle) { Sessionparam = vi; EventTypeparam = etype; Addressparam = userHandle; viGetAttribute (event, VI_ATTR_STATUS, &StatusSession); viGetAttribute (event, VI_ATTR_RET_COUNT, &RdCount); stopflag = VI_TRUE; return VI_SUCCESS; } int main (void) { /* * First we open a session to the VISA resource manager. We are * returned a handle to the resource manager session that we must * use to open sessions to specific instruments. */ status = viOpenDefaultRM (&defaultRM); if (status < VI_SUCCESS) { printf("Could not open a session to the VISA Resource Manager!\n"); exit (EXIT_FAILURE); } /* * Next we use the resource manager handle to open a session to a * GPIB instrument at device 2. A handle to this session is * returned in the handle inst. Please consult the NI-VISA User Manual * for the syntax for using other instruments. */ status = viOpen (defaultRM, "GPIB::2::INSTR", VI_NULL, VI_NULL, &inst); /* * Now we install the handler for asynchronous i/o completion events. * To install the handler, we must pass our instrument session, the type of * event to handle, the handler function name and a user handle * which acts as a handle to the handler function. */ status = viInstallHandler (inst, VI_EVENT_IO_COMPLETION, AsyncHandler, uhandle); /* Now we must actually enable the I/O completion event so that our * handler will see the events. Note, one of the parameters is * VI_HNDLR indicating that we want the events to be handled by * an asynchronous event handler. The alternate mechanism for handling * events is to queue them and read events off of the queue when * you want to check them in your program. */ status = viEnableEvent (inst, VI_EVENT_IO_COMPLETION, VI_HNDLR, VI_NULL); /* * Now the VISA write command is used to send a request to the * instrument to generate a sine wave. This demonstrates the * synchronous read operation that blocks the application until viRead() * returns. Note that the command syntax is instrument specific. */ /* * Here you specify which string you wish to send to your instrument. * The command listed below is device specific. You may have to change * command to accommodate your instrument. */ strcpy(stringinput,"SOUR:FUNC SIN; SENS: DATA?\n"); BytesToWrite = (ViUInt32)strlen(stringinput); status = viWrite (inst, (ViBuf)stringinput,BytesToWrite, &rcount); /* * Next the asynchronous read command is called to read back the * date from the instrument. Immediately after this is called * the program goes into a loop which will terminate * on an i/o completion event triggering the asynchronous callback. * Note that the asynchronous read command returns a job id that is * a handle to the asynchronous command. We can use this handle * to terminate the read if too much time has passed. */ status = viReadAsync (inst, data, READ_BUFFER_SIZE - 1, &job); printf("\n\nHit enter to continue."); letter = getchar(); /* * If the asynchronous callback was called and the flag was set * we print out the returned data otherwise we terminate the * asynchronous job. */ if (stopflag == VI_TRUE) { /* RdCount was set in the callback */ /* Add a NULL terminator to the read buffer */ data[RdCount] = '\0'; printf ("Here is the data: %s", data); } else { status = viTerminate (inst, VI_NULL, job); printf("The asynchronous read did not complete.\n"); } printf ("\nHit enter to continue."); fflush(stdin); getchar(); /* * Now we close the instrument session and the resource manager * session to free up resources. */ status = viClose(inst); status = viClose(defaultRM); return 0; }