⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can_ixxat.cpp

📁 美国COPLEY驱动器,程序开发工具之一.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
{
	mutex.Lock();
	if( open )
	{
		lpVCI_CancelBoard( handle );
		boardMutex.Lock();
		for( int i=0; i<MAX_BOARDS; i++ )
		{
			if( board[i] == this )
				board[i] = NULL;
		}
		boardMutex.Unlock();

		open = 0;
		UninitLibrary();
	}
	mutex.Unlock();
	return 0;
}

/***************************************************************************/
/**
Set the CAN interface baud rate.
@param b The baud rate to set.
@return A pointer to an error object on failure, or NULL on success.
*/
/***************************************************************************/
const Error *IxxatCAN::SetBaud( int32 b )
{
	switch( b )
	{
		case   10000: bt0=0x31; bt1=0x1C; break;
		case   20000: bt0=0x18; bt1=0x1C; break;
		case   50000: bt0=0x09; bt1=0x1C; break;
		case  100000: bt0=0x04; bt1=0x1C; break;
		case  125000: bt0=0x03; bt1=0x1C; break;
		case  250000: bt0=0x01; bt1=0x1C; break;
		case  500000: bt0=0x00; bt1=0x1C; break;
		case  800000: bt0=0x00; bt1=0x16; break;
		case 1000000: bt0=0x00; bt1=0x14; break;
		default: return &CanError::BadParam;
	}

	baud = b;
	return 0;
}

/***************************************************************************/
/**
Receive the next CAN frame.  
@param frame A reference to the frame object that will be filled by the read.
@param timeout The timeout (ms) to wait for the frame.  A timeout of 0 will
       return immediately if no data is available.  A timeout of < 0 will 
		 wait forever.
@return A pointer to an error object on failure, or NULL on success.
*/
/***************************************************************************/
const Error *IxxatCAN::RecvFrame( CanFrame &frame, int32 timeout )
{
	if( !open )
		return &CanError::NotOpen;

	const Error *err = rxSem.Get( timeout );
	if( err ) return err;

	mutex.Lock();
	frame = rx[rxTail];

	int newTail = rxTail+1;
	if( newTail >= IXXAT_RX_QUEUE_SZ )
		newTail = 0;

	rxTail = newTail;
	mutex.Unlock();

	return 0;
}

/***************************************************************************/
/**
Write a CAN frame to the CAN network.
@param frame A reference to the frame to write.
@param timeout The time to wait for the frame to be successfully sent.
       If the timeout is 0, the frame is written to the output queue and
		 the function returns without waiting for it to be sent.
		 If the timeout is <0 then the function will delay forever.
@return A pointer to an error object on failure, or NULL on success.
*/
/***************************************************************************/
const Error *IxxatCAN::XmitFrame( CanFrame &frame, int32 timeout )
{
   // don't allow frame lengths longer than 8
	if( frame.length > 8 )
		return &CanError::BadParam;

	mutex.Lock();

	if( !open )
	{
		mutex.Unlock();
		return &CanError::NotOpen;
	}

	int ret;

	switch( frame.type )
	{
		case CAN_FRAME_DATA:
			ret = lpVCI_TransmitObj( handle, txQueue, frame.id, frame.length, frame.data );
			break;
		case CAN_FRAME_REMOTE:
			ret = lpVCI_RequestObj( handle, txQueue, frame.id, frame.length );
			break;
		default:
			mutex.Unlock();
			return &CanError::BadParam;
	}

	mutex.Unlock();

	return ConvertError( ret );
}


/***************************************************************************/
/**
Convert error codes defined by the Vector CAN library into 
the standard error codes used by the motion library.
@param err The Vector style status code
@return A pointer to an error object, or NULL if no error is indicated
*/
/***************************************************************************/
const Error *IxxatCAN::ConvertError( int err )
{
	switch( err )
	{
		case VCI_OK:          return 0;
		case VCI_ERR:         return &CanError::Driver;
		case VCI_HWSW_ERR:    return &CanError::Driver;
		case VCI_SUPP_ERR:    return &CanError::Driver;
		case VCI_PARA_ERR:    return &CanError::Driver;
		case VCI_RES_ERR:     return &CanError::Driver;
		case VCI_QUE_ERR:     return &CanError::Driver;
		case VCI_TX_ERR:      return &CanError::Driver;
		default:              return &CanError::Unknown;
	}
}

/***************************************************************************/
/**
Receive interrupt handler.  This is an internal function that should not 
be called except by the driver.  It's used to add one or more CAN frames
to the receive buffer when they are received.

@param ct The number of frames to add
@param ptr Points to an array of ct VCI_CAN_OBJ structures.
*/
/***************************************************************************/
void IxxatCAN::rxInt( int16 ct, void *ptr )
{
	VCI_CAN_OBJ *frame = (VCI_CAN_OBJ*)ptr;

	for( int i=0; i<ct; i++ )
	{
		int newHead = rxHead+1;
		if( newHead >= IXXAT_RX_QUEUE_SZ )
			newHead = 0;
	
		if( newHead == rxTail )
			return;
	
		rx[ rxHead ].id       = frame[i].id;
		rx[ rxHead ].length   = frame[i].len;

		if( frame[i].rtr )
			rx[ rxHead ].type = CAN_FRAME_REMOTE;
		else
			rx[ rxHead ].type = CAN_FRAME_DATA;

		for( int j=0; j<8; j++ )
			rx[ rxHead ].data[j] = frame[i].a_data[j];

		rxHead = newHead;
		rxSem.Put();
	}
}

/***************************************************************************/
/**
Local interrupt handlers.  These just call the member function for the
CAN object.
*/
/***************************************************************************/
#define RX_INT(x)  static void VCI_CALLBACKATTR rxInt##x( UINT16 q, UINT16 ct, VCI_CAN_OBJ *p ) \
                   { if( board[x] ) board[x]->rxInt( ct, p ); }

RX_INT(0);
RX_INT(1);
RX_INT(2);
RX_INT(3);

/***************************************************************************/
/**
Initialize the Ixxat .dll function pointers.  This internal method is called
at startup and used to initialize some local pointers to functions in the 
Ixxat supplied .dll files.
@return A pointer to an error object or NULL on success.
*/
/***************************************************************************/
static const Error *InitLibrary( void )
{
	const Error *err = 0;
	libraryMutex.Lock();

	if( !openCards )
	{
		// Load the Ixxat .dll files
		hReg = LoadLibrary("xat11reg.dll");
		if( !hReg )
		{
			cml.Error( "Unable to load library file: xat11reg.dll\n" );
			err = &CanError::NoDriver;
			goto done;
		}

		hVCI = LoadLibrary("vci11un6.dll");
		if( !hVCI )
		{
			FreeLibrary( hReg );
			cml.Error( "Unable to load library file: vci11un6.dll\n" );
			err = &CanError::NoDriver;
			goto done;
		}

		lpXAT_SelectHardware    = (XAT_SelectHardwareType)   GetProcAddress( hReg, "XAT_SelectHardware"    );
		lpXAT_GetConfig         = (XAT_GetConfigType)        GetProcAddress( hReg, "XAT_GetConfig"         );
		lpXAT_GetDefaultHwEntry = (XAT_GetDefaultHwEntryType)GetProcAddress( hReg, "XAT_GetDefaultHwEntry" );
		lpVCI_StartCan          = (VCI_StartCanType)         GetProcAddress( hVCI, "VCI_StartCan"          );
		lpVCI_AssignRxQueObj    = (VCI_AssignRxQueObjType)   GetProcAddress( hVCI, "VCI_AssignRxQueObj"    );
		lpVCI_ConfigQueue       = (VCI_ConfigQueueType)      GetProcAddress( hVCI, "VCI_ConfigQueue"       );
		lpVCI_SetAccMask        = (VCI_SetAccMaskType)       GetProcAddress( hVCI, "VCI_SetAccMask"        );
		lpVCI_InitCan           = (VCI_InitCanType)          GetProcAddress( hVCI, "VCI_InitCan"           );
		lpVCI2_PrepareBoard     = (VCI2_PrepareBoardType)    GetProcAddress( hVCI, "VCI2_PrepareBoard"     );
		lpVCI_CancelBoard       = (VCI_CancelBoardType)      GetProcAddress( hVCI, "VCI_CancelBoard"       );
		lpVCI_TransmitObj       = (VCI_TransmitObjType)      GetProcAddress( hVCI, "VCI_TransmitObj"       );
		lpVCI_RequestObj        = (VCI_RequestObjType)       GetProcAddress( hVCI, "VCI_RequestObj"        );


		if( !lpXAT_SelectHardware || !lpXAT_GetConfig || !lpXAT_GetDefaultHwEntry || 
			 !lpVCI_StartCan || !lpVCI_AssignRxQueObj || !lpVCI_ConfigQueue || 
			 !lpVCI_SetAccMask || !lpVCI_InitCan || !lpVCI2_PrepareBoard || 
			 !lpVCI_CancelBoard || !lpVCI_TransmitObj || !lpVCI_RequestObj )
		{
			err = &CanError::NoDriver;
			FreeLibrary( hVCI );
			FreeLibrary( hReg );
		}
	}

	if( !err )
		openCards++;

done:
	libraryMutex.Unlock();
	return err;
}

/***************************************************************************/
/**
Free the library pointers if they are no longer accessed.
@return A pointer to an error object or NULL on success
*/
/***************************************************************************/
static void UninitLibrary( void )
{
	libraryMutex.Lock();
	if( --openCards == 0 )
	{
		FreeLibrary( hVCI );
		FreeLibrary( hReg );
	}
	libraryMutex.Unlock();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -