In our application we have to receive large amounts of data (100 Mbytes) through CAN bus from a microcontroller (C505CA) to a PC. We are using a PCMCIA CAN card and writing program in Borland C. NI-CAN driver versions 1.5 and 1.51 are used.
We encountered two problems:
- We get a notification only when the receive buffer is nearly full. The remaining time is not enough for the program to read out frames and some frames get lost. We tried to set up notification for 1/4-th of the buffer size but we always get the notification when the read queue is nearly full. When these frames are lost the sending MC still sees an acknowledge bit and cannot determine whether the frame was received or not.
This error happens when we send at 1 Mbaud, 8 data bytes/frame and about one frame sent every 250 microsec.
- If we send frames faster we get a RXQueueOverflow error message. We tried to overcome this by setting
NC_ATTR_RX_Q_LEN. However, in this case we always get an error message during initialization.
My question is how we can get optimum receive performance, and what is the proven data receive rate using NI-CAN?
I copy a piece of code below which shows how initialization is done:
bool CanbusClass::Initialize( char* Bus, int Speed)
{
int ReadQueueSize =250
ObjName = Bus;
BaudRate = Speed;
// Configure the CAN Network Interface Objects.
// Set baud rate as specified above.
AttrIdList[0] = NC_ATTR_BAUD_RATE;
AttrValueList[0] = BaudRate;
// Start communication as soon as the CAN Object of this network interface
port is opened.
AttrIdList[1] = NC_ATTR_START_ON_OPEN;
AttrValueList[1] = NC_TRUE;
// Set the read queue length to 1250, and the write queue length to zero.
AttrIdList[2] = NC_ATTR_READ_Q_LEN;
AttrValueList[2] = ReadQueueSize;
AttrIdList[3] = NC_ATTR_WRITE_Q_LEN;
AttrValueList[3] = 1;
// Set the standard and extended comparators and masks such that all CAN
data frames are received
AttrIdList[4] = NC_ATTR_CAN_COMP_STD;
AttrValueList[4] = 0;
AttrIdList[5] = NC_ATTR_CAN_MASK_STD;
AttrValueList[5] = NC_CAN_MASK_STD_DONTCARE;
AttrIdList[6] = NC_ATTR_CAN_COMP_XTD;
AttrValueList[6] = 0;
AttrIdList[7] = NC_ATTR_CAN_MASK_XTD;
AttrValueList[7] = NC_CAN_MASK_XTD_DONTCARE;
AttrIdList[8] = NC_ATTR_NOTIFY_MULT_SIZE;
AttrValueList[8] = ReadQueueSize / 4;
AttrIdList[9] = NC_ATTR_RX_Q_LEN;
AttrValueList[9] = ReadQueueSize / 4;
// Reset
Status = ncReset( Bus, 0 );
if( CheckStat(Status, "ncReset",true) )
{
// Configuration
Status = ncConfig(ObjName, 10, AttrIdList, AttrValueList);
if( CheckStat(Status, "ncConfig",true) )
{
// Open the object.
Status = ncOpenObject(ObjName, &GlobalObjh);
if( CheckStat(Status, "ncOpenObject",true) )
{
// Create the notification used to store incoming frames.
Status = ncCreateNotification( GlobalObjh, (NC_ST_READ_AVAIL |
NC_ST_READ_MULT | NC_ST_ERROR), NC_DURATION_INFINITE, &InputQueue,
EventCallback);
if( CheckStat(Status, "ncCreateNotification",true) )
return true;
}
}
}
return false;
}