LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

When receiving RS232 data, some data is sometimes lost - any ideas?

I have a CVI program that sends and receives data via COM1 at 115200 baud. Data is sent in small blocks of up to 60 bytes. All handshaking is disabled, and the DTR, RTS, DSR and CTS pins are connected together in the lead. Sometimes the CVI program fails to receive some data. We have attached an analysis program that confirms that the data is being sent by the other device (a PIC). Calling GetComStat() returns zero. Calling GetComLineStatus() returns 0x30 - CTS and DSR set. The problem occurs in debug and release modes, and under Windows 98 and Windows 2000.
Please, can you help?
0 Kudos
Message 1 of 8
(5,593 Views)
Margaret,

Can you post your routine to this thread? Is the whole data block missed, or just some bytes? Are any bytes received incorrectly or are some just missed?

Regards

Jamie Fraser
0 Kudos
Message 2 of 8
(5,590 Views)
Some bytes are lost, not the whole data block missed. Bytes seem to be missed completely, not received incorrectly.
A complete operation involves transfer of data between PC and PIC: the PC initiates all transactions and expects an ASCII reply to each block of data it sends. The ASCII blocks end with a newline. The blocks start with a message number and a space. Thousands of characters transfer satisfactorily, then (for no apparent reason) the end of a message is not received. The receive routine waits for a newline and times out if it does not get one.

Here is the code for the receive routine. As you can see, I've added diagnostic bits to try to find out what is happening.
When a timeout occurs, GetComStat() returns 0000, GetComLineStatus() returns 0x30 and ReturnRS232Err() returns 0.

static CHAR Rxstr[MAXCOLS+1], pos;
int RxMssg (void)
{
int ich, error;
double starttime, time;

SetMouseCursor (VAL_HOUR_GLASS_CURSOR);
starttime = Timer ();
while (TRUE)
{
while (GetInQLen(Port) >= 1)
{
ich = ComRdByte (Port);
if (ich == '\n')
{
if (pos < 2)
{
strcpy (MssgStr, "Received ");
if (pos)
sprintf (MssgStr+strlen(MssgStr), "%02xh ", *Rxstr);
sprintf (MssgStr+strlen(MssgStr), "%02xh ", ich);
SetMouseCursor (VAL_DEFAULT_CURSOR);
return NEGERROR;
}
MssgNo = *Rxstr - '0';
if ((MssgNo >= 0) && (MssgNo < PROG_NMSSGS))
{
*(Rxstr+pos) = '\0';
strcpy (MssgStr, Rxstr+2);
pos = 0;
SetMouseCursor (VAL_DEFAULT_CURSOR);
return OK;
}
else
pos=0;
}
else if ((ich > 0x1f) && (ich < 0x80))
{
*(Rxstr+pos) = ich;
if (pos < MAXCOLS)
pos++;
}
}
time = Timer ();
if ((time - starttime) > 5)
{
*(Rxstr+pos) = '\0';
strcpy (MssgStr, Rxstr);
pos = 0;
// 0001 Input character were lost because the input queue filled.
// 0002 Internal input queue error.
// 0010 Parity error detected.
// 0020 Overrun error detected.
// 0040 Framing error detected.
// 0080 Break signal was detected.
// 1000 The remote system has sent an XOFF character.
// If XON/XOFF mode has been enabled, characters will not be moved
// from the output queue to the RS-232 port until XON is received from the remote system.
// 4000 An XOFF character was sent to the remote system.
error = GetComStat (Port);
sprintf (MssgStr+strlen(MssgStr), "\nComm Status = %04xh", error);

//kRS_CTS_ON 0x10 The CTS (clear-to-send) signal is on.
//kRS_DSR_ON 0x20 The DSR (data-set-ready) signal is on.
//kRS_RING_ON 0x40 The ring indicator signal is on.
//kRS_RLSD_ON 0x80 The RLSD (receive-line-signal-detect) signal is on.
error = GetComLineStatus (Port);
sprintf (MssgStr+strlen(MssgStr), "\nLine Status = %04xh", error);
error = ReturnRS232Err ();
if (error)
sprintf (MssgStr+strlen(MssgStr), "\nRS232 error %d: %s", error, GetRS232ErrorString (error));

SetMouseCursor (VAL_DEFAULT_CURSOR);
return NEGERROR;
}
}
}
0 Kudos
Message 3 of 8
(5,562 Views)
Margaret,

I have had a quick look at your code and all I can suggest is ANDing ich with 0x80 before doing your conditional tests to ensure the top bit is not set (see help for ComRdByte()).

Good luck.
0 Kudos
Message 4 of 8
(5,531 Views)
Margaret,
Sorry, I meant 0x7F not 0x80.
0 Kudos
Message 5 of 8
(5,517 Views)
Thanks for trying to help, Jamie!
I have managed to overcome the problem in 2 ways:
one is to reinitialise the port after getting a timeout, and then resend the message
the other is touse a shorter comms lead!
I deduce that the problem is hardware related, but I would have hoped to have got an error indication from CVI that would help to diagnose it.
I would be very interested to know if anyone else has had similar problems.
0 Kudos
Message 6 of 8
(5,499 Views)
I've had serious problems using RS-232 communication between a PIC and a Windows box. I've found that when running with very fast baud rates, the UART on the PC fills up more quickly than Windows can empty it. Without using some type of flow control, the buffer overflows and data is lost. I would recommend implementing a simple hardware flow control procedure in the PIC (which has no built-in hardware flow control capability). Simply watch the state of the DTR line coming from the PC and stop sending data when it is deasserted. Once Windows catches up, it will reassert DTR and the PIC should then continue to send data.
0 Kudos
Message 7 of 8
(5,432 Views)
Hi, Luke
Thanks for the advice. I've had similar problems in the past, with the PC receive buffer overflowing, but I've got round it in this project by sending fairly small blocks of data, and handshaking each one. The PC initiates all communications, and all data blocks are much smaller tham the PC receive buffer.
Regards,
Margaret
0 Kudos
Message 8 of 8
(5,417 Views)