Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

a problem with ibrd and ibcntl

I have a PIX-GPIB board and 488.2 version 1.7 software

I am having a problem with ibrd and ibcntl api calls used in a VC++6.0 program on Win2k Professional.

I get transferred data using ibrd() and ibcntl.

When ibrd() terminates within the timeout, ibcntl's value is set up sometimes fewer than the actual number of bytes transferred.
(It is 2 or 3 bytes fewer than the placed data in the buffer.)

Isn't the value of ibcntl guaranteed when it ends by the timeout?

If not guaranteed, please teach me how to take the transmitted data certainly.

Best Regards,

Skura
0 Kudos
Message 1 of 4
(5,169 Views)
Hi,

I have been checking the NI-488.2 API user manual looking for any case where ibcnt might be considered invalid. Ibcnt should be valid everytime ibrd is called.

I wanted to ask you: What kind of data are you receiving, binary or ASCII?. Also, how do you determine the actual number of bytes returned by the driver?. Since you are programming in C, the only thing that indicates the end of string is the NULL character. The driver does not terminate the string. On the example you'll see the following line after calling ibrd:

buffer[ibcnt] = '\0'

to terminate the string.

I'd like to see what kind of data are you receiving. For example, initially the buffer is filled with zeros. If you get 5 characters, you'll see a string length of 5. If
you receive 4 characters and use the same buffer, the fifth element is not NULL so the string length will still be 5 characters.

Hope this helps.

DiegoF
0 Kudos
Message 2 of 4
(5,168 Views)
Hi DiegoF

Thank you for your help.

I am receiving both data(binary and ASCII).


I put sample programs(Controller side & Device side) on below for this trouble.

A controller side program sends data 11 times every 3 seconds.
Data length is 131072 bytes and is fill uped with FF.

A device side program receives data and displays the data length and status which were received.


Execution usually displays the following message for every end of 1 data transmission.

[Status<0x2144> ERR:OFF END:ON CMPL:ON REM:ON LACS:ON ibcntl:1024 accum:131072 strlen:131072]

but occasionally displays the following messages.

[Status<0x2144> ERR:OFF END:ON CMPL:ON REM:ON LACS:ON ibcntl:1024 accum:131070 strlen:131070]

This shows that receive the sent data (131072) can be being finished.

========== Device side program ==========

#include
#include "decl-32.h"

#include

void main( int argc, char *argv[] )
{
int gpibDev;
int status;
int address = 1;
int INPUT_BUFFER_SIZE = 1000000;
int nTimeOut = T10ms;

printf("Address:%d\n", address);

gpibDev = ibfind("gpib0");
if (gpibDev < 0)
{
printf("ibfind error\n");
exit(1);
}
if (ibpad(gpibDev, address) & ERR)
{
printf("ibpad error\n");
exit(1);
}
if (ibsad(gpibDev, 0) & ERR)
{
printf("ibsad error\n");
exit(1);
}
if (ibconfig(gpibDev, IbcCICPROT, FALSE) & ERR)
{
printf("IbcCICPROT error\n");
exit(1);
}

if (ibconfig(gpibDev, IbcAUTOPOLL, FALSE) & ERR)
{
printf("IbcAUTOPOLL error\n");
exit(1);
}
if (ibconfig(gpibDev, IbcEOSchar, 0x0a) & ERR)
{
printf("IbcEOSchar error\n");
exit(1);
}
if (ibconfig(gpibDev, IbcEOScmp, TRUE) & ERR)
{
printf("IbcEOScmp error\n");
exit(1);
}
if (ibconfig(gpibDev, IbcEOSrd, FALSE) & ERR)
{
printf("IbcEOSrd error\n");
exit(1);
}
if (ibconfig(gpibDev, IbcEOSwrt, FALSE) & ERR)
{
printf("IbcEOSwrt error\n");
exit(1);
}
if (ibconfig(gpibDev, IbcEndBitIsNormal, TRUE) & ERR)
{
printf("IbcEndBitIsNormal error\n");
exit(1);
}
if (ibconfig(gpibDev, IbcTIMING, 1) & ERR)
{
printf("IbcTIMING error\n");
exit(1);
}
if (ibconfig(gpibDev, IbcHSCableLength, 0) & ERR)
{
printf("IbcHSCableLength error\n");
exit(1);
}
if (ibdma(gpibDev, FALSE) & ERR)
{
printf("ibdma error\n");
exit(1);
}
if (ibtmo(gpibDev, nTimeOut) & ERR)
{
printf("ibtmo error\n");
exit(1);
}

unsigned char *inBuff = NULL;
int accumCount = 0;

if( NULL == ( inBuff = (unsigned char *)malloc( INPUT_BUFFER_SIZE + 1 ) ) )
{
printf("malloc error\n");
exit(1);
}

while (1)
{
status = ibwait(gpibDev, LACS | TIMO);
if (status & ERR)
{
printf("ibwait error\n");
if( NULL != inBuff )
{
free( inBuff );
inBuff = NULL;
}
exit(1);
}

while (status & LACS)
{
if( accumCount == 0 )
memset( inBuff, '\0', INPUT_BUFFER_SIZE + 1 );
status = ibrd(gpibDev, inBuff+accumCount, INPUT_BUFFER_SIZE - accumCount );

if( ibcntl > 0 )
{
accumCount += ibcntl;

printf( "Status<0x%04x> ", status );

if( status & ERR ) printf("ERR:ON "); /* Error detected */
else printf("ERR:OFF ");
if( status & TIMO ) printf("TIMO:ON "); /* Timeout */
if( status & END ) printf("END:ON "); /* EOI or EOS detected */
if( status & SRQI ) printf("SRQI:ON "); /* SRQ detected by CIC */
if( status & RQS ) printf("RQS:ON "); /* Device needs service */
if( status & CMPL ) printf("CMPL:ON "); /* I/O completed */
if( status & LOK ) printf("LOK:ON "); /* Local lockout state */
if( status & REM ) printf("REM:ON "); /* Remote state */
if( status & CIC ) printf("CIC:ON "); /* Controller-in-Charge */
if( status & ATN ) printf("ATN:ON "); /* Attention asserted */
if( status & TACS ) printf("TACS:ON "); /* Talker active */
if( status & LACS ) printf("LACS:ON "); /* Listener active */
if( status & DTAS ) printf("DTAS:ON "); /* Device trigger state */
if( status & DCAS ) printf("DCAS:ON "); /* Device clear state */

printf( "ibcntl:%d accum:%d strlen:%d \n", ibcntl, accumCount, strlen((char *)inBuff) );

if( status & ERR )
{

}
else
{
accumCount = 0;
}
}
}
}
if( NULL != inBuff )
{
free( inBuff );
inBuff = NULL;
}
}

==============================

========== Controller side program ==========

#include "windows.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "ni488.h"

#define BUF_SIZE 1024
int dev;

void send( const int sleepms )
{
unsigned char data = 0xff;
int numBits = 1024 * 1024;

if (ibeot(dev, 0) & ERR)
{
printf("ibeot 0 error %d\n", iberr);
exit(1);
}
int numBytes;
if (numBits % 😎
numBytes = numBits / 8 + 1;
else
numBytes = numBits / 8;

unsigned char buf[BUF_SIZE];
memset( buf, data, BUF_SIZE );

int bytesRemain = numBytes;
int count = 0;
while (1)
{
count++;
int writeSize = BUF_SIZE;
if (bytesRemain < writeSize)
writeSize = bytesRemain;
bytesRemain -= writeSize;
printf("%d ", count);
if (bytesRemain > 0)
{
ibwrt(dev, buf, writeSize);
}
else
{
if (ibeot(dev, 1) & ERR)
{
printf("ibeot 1 err %d\n", iberr);
exit(1);
}
if (ibwrt(dev, buf, writeSize) & ERR)
{
printf("ibwrt err %d\n", iberr);
exit(1);
}
break;
}
Sleep(sleepms);
}
printf("transferred : %d bytes\n", numBytes );
}

void main(int argc, char *argv[])
{
int n;

dev = ibdev(0, 1, 0, T3s, 1, 0);

for( n=0 ; n<=100 ; n=n+10 )
{
printf( "\n wait: %d ms\n", n );
send( n );
Sleep(3000);
}
printf("\n fin \n");
Sleep(10 * 1000 );
}

==============================

Best Regards,

Skura
0 Kudos
Message 3 of 4
(5,168 Views)
Hi,

I didn't realize you had place a reply. My subscription to this posting must have expired before you posted.

I tested the code you pasted. I was able to reproduce the problem. On some transfers I got a final transfer of 131071.

I suspect it might be related to the CPU load. On one test I placed some load on the CPU and got a final transfer of 131068.

You could try to enable DMAs and increase slightly the timeout value. I going to do some more testing and look into the problem in more detail.

DiegoF
National Intruments
0 Kudos
Message 4 of 4
(5,168 Views)