Automotive and Embedded Networks

cancel
Showing results for 
Search instead for 
Did you mean: 

NI PCI-CAN/2 Serie 2 100% Busload

Hi all,

 

I'm trying to generate 100% "NI PCI-CAN/2 Serie 2" card, but I'm only able to reach 60% with 8byte CAN frames and 35% with 1byte CAN frames. I'm using the "CAN Transmit Multiple" example:

 

loop:

   //write the frames to the board    
   Status = ncWriteMult (TxHandle0, sizeof(Transmit0), Transmit0);
   //wait until the last frame is send out            
   Status = ncWaitForState (TxHandle0, NC_ST_WRITE_SUCCESS, 2000, 0);

   //This is faster than using ncWaitForState (TxHandle0, NC_ST_WRITE_MULT, 200, 0)

 

 

However there is always a ~85uS gap between the CAN frames. (I'm looping back to the second CAN channel of the card.)

Does anyone have an idea how to fix this?

 

Regards,

mskr

 

0 Kudos
Message 1 of 5
(5,614 Views)

A real 100% bus load is not something you can really do.  There is priority in messaging and as a result your buffer will be filled with messages that can't go out and it will return errors, which will probably prevent new messages from going out.

 

That being said if you want to fille the transmission why are you relying on software timing?  Just throw 100 new messages on the buffer every millisecond and you'll have 100%.

0 Kudos
Message 2 of 5
(5,597 Views)

Thanks for your answer. However, I think I do not rely on SW timing. I throw in 128/256 messages every time the buffer has been transmitted or tells me that there are free slots. Nevertheless I have the behaviour I described above (gaps between each and every frame). (At a baudrate of 50kBit I can reach a bus load of 98% which drops continually if a increase the baudrate...)

0 Kudos
Message 3 of 5
(5,557 Views)

Where does it say in your sudo code you are putting in 128 messages?  I see one write taking place, then a wait until that message has been sent out. Posting actual code (preferable in the form of a VI) is more helpful.

0 Kudos
Message 4 of 5
(5,554 Views)

Sorry for not posting the whole code but only the loop fragment - but here it is:

 

/*
CAN Transmit multiple.c

Demonstrates how to transmit multiple CAN Frames in one Burst via the Network Interface.
Time Difference is related to the first frame which always has to have a timestamp of zero.
In Timestamp Mode, these frames will be sent out using the specified time differences.
In Immediate Mode all frames will be send out back to back in one burst.
*/
#include <stdio.h>      // Include file for printf
#include <stdlib.h>     // Include file for strtol
#include <windows.h>    // Include file for Win32 time functions
#include <conio.h>      // Include file for _getch/_kbhit
#include <string.h>
#include "Nican.h"      // Include file for NI-CAN functions and constants       

#define NUM_TX_CNT 256

/* NI-CAN handles */
NCTYPE_OBJH TxHandle=0;

/* Print a description of an NI-CAN error/warning. */
  void PrintStat(NCTYPE_STATUS status, char *source)
{
   char statusString[1024];
     
   if (status != 0) 
   {
      ncStatusToString(status, sizeof(statusString), statusString);
      printf("\n%s\nSource = %s\n", statusString, source);
   
// close object handle, then exit.  
      ncCloseObject(TxHandle);
      exit(1);     
   }
}

int getch_noblock() 
{
	if (_kbhit())
		return _getch();
	else
		return -1;
}

int main ()
{
	NCTYPE_CAN_STRUCT	Transmit[NUM_TX_CNT];
	NCTYPE_UINT32		TXMode = 0;
	NCTYPE_ATTRID		AttrIdList[8];
	NCTYPE_UINT32		AttrValueList[8];
	NCTYPE_UINT32		Baudrate = 1000000;
	NCTYPE_STATUS		Status;
	char				Interface[7] = "CAN0";
	int					NumFrames = NUM_TX_CNT;
	int					iDataLoop, iLoop;
	int					ch;
	int					frame_id_curr, frame_id_cnt;
	unsigned int        packet_cnt = 0;
	
/* Configure the CAN Network Interface Object */
	AttrIdList[0] =         NC_ATTR_BAUD_RATE;   
	AttrValueList[0] =      Baudrate;
	AttrIdList[1] =         NC_ATTR_START_ON_OPEN;
	AttrValueList[1] =      NC_FALSE;
	AttrIdList[2] =         NC_ATTR_READ_Q_LEN;
	AttrValueList[2] =      0;
	AttrIdList[3] =         NC_ATTR_WRITE_Q_LEN;
	AttrValueList[3] =      NumFrames;
	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;
    
	Status = ncConfig(Interface, 8, AttrIdList, AttrValueList);	
	if (Status < 0) 
	{
		PrintStat(Status, "ncConfig");
	}
    
	/* open the CAN Network Interface Object */
	Status = ncOpenObject(Interface, &TxHandle);
	if (Status < 0) 
	{
		PrintStat(Status, "ncOpenObject");       
	}

	for(iLoop = 0; iLoop < NUM_TX_CNT; iLoop++)	  
	{
		Transmit[iLoop].ArbitrationId = iLoop;
		Transmit[iLoop].DataLength = 8;
		Transmit[iLoop].FrameType = NC_FRMTYPE_DATA;
		//Transmit[iLoop].Timestamp.HighPart = 0;
		/* The Timestamp resolution is ms, so only the low part is needed as multiple of 100ns */ 
		//Transmit[iLoop].Timestamp.LowPart = time_dff[iLoop]*10000;   
	} 	

	/* print out the instructions to the I/O window */		
	printf("\nRunning on CAN0 ...\n\nPress 't' to transmit the frames  timestamped (PXI/PCI/PCMCIA only)");
	printf("\n\nPress 'n' to transmit the frames  back to back\n\nPress 'q' to quit\n\n");

	/*Transmit frames each time the user selects to*/
	frame_id_curr = 0;
	do
	{
		ch = _getch();
		if (ch == 'n')
		{  
			int ch1;
			//Start Communication with ncAction
			Status = ncAction (TxHandle, NC_OP_START, 0);
			if (Status < 0) 
			{
				PrintStat(Status, "ncAction");      
			}

			frame_id_curr = 0;
			frame_id_cnt = 0;

			packet_cnt = 1;

			do {
				ch1 = getch_noblock();
				for (iLoop = 0; iLoop < NUM_TX_CNT; iLoop++)
				{
					Transmit[iLoop].ArbitrationId = frame_id_curr++;
					memset(Transmit[iLoop].Data, 0, 8);
					*((unsigned int *)(Transmit[iLoop].Data)) = packet_cnt++;
					if (frame_id_curr == 0x800)
					{
						frame_id_curr = 0;
						frame_id_cnt++;
					}
				}

				//write the frames to the board	
				Status = ncWriteMult (TxHandle, sizeof(Transmit), Transmit);
				if (Status < 0) 
				{
					PrintStat(Status, "ncWrite");
				}

				//wait until the last frame is send out			
				Status = ncWaitForState (TxHandle, NC_ST_WRITE_SUCCESS, 2000, 0);
				if (Status < 0) 
				{
					PrintStat(Status, "ncWaitForState1");      
				}

				//wait until there is free space
				//do {
				//	Status = ncWaitForState (TxHandle, NC_ST_WRITE_MULT, 200, 0);
				//} while (Status < 0);
				

			} while (ch1 == -1);

			//wait until the last frame is send out			
			Status = ncWaitForState (TxHandle, NC_ST_WRITE_SUCCESS, 2000,0);
			if (Status < 0) 
			{
				PrintStat(Status, "ncWaitForState");      
			}

			//stop communication to set the TXMode for the next write		
			Status = ncAction (TxHandle, NC_OP_STOP, 0);
			if (Status < 0) 
			{
				PrintStat(Status, "ncAction");      
			}
		}
		
		Sleep(100);
	} while (ch != 'q');

	/* Close the Network Interface Object */
	Status = ncCloseObject(TxHandle);
    
	if (Status < 0)
	{
		PrintStat(Status, "ncCloseObject");
	}

return 0;	
}

0 Kudos
Message 5 of 5
(5,540 Views)