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

📄 can_ixxat.cpp

📁 美国COPLEY驱动器,程序开发工具之一.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/************************************************************/
/*                                                          */
/*  Copley Motion Libraries                                 */
/*                                                          */
/*  Author: Stephen Glow & Chris Jones                      */
/*                                                          */
/*  Copyright (c) 2002-2005 Copley Controls Corp.           */
/*                          http://www.copleycontrols.com   */
/*                                                          */
/************************************************************/

/*
	CAN object for IXXAT CAN driver
	(see http://www.ixxat.com for more information on the IXXAT VCI driver for the VCI series cards)
*/

#include <cstdio>
#include <cstring>
#include <windows.h>

#include "CML.h"
#include "can_ixxat.h"
#include "XatXXReg.h"
#include "VCI2.h"

CML_NAMESPACE_USE();

/* local functions */
static void VCI_CALLBACKATTR rxInt0( UINT16 q, UINT16 ct, VCI_CAN_OBJ *p );
static void VCI_CALLBACKATTR rxInt1( UINT16 q, UINT16 ct, VCI_CAN_OBJ *p );
static void VCI_CALLBACKATTR rxInt2( UINT16 q, UINT16 ct, VCI_CAN_OBJ *p );
static void VCI_CALLBACKATTR rxInt3( UINT16 q, UINT16 ct, VCI_CAN_OBJ *p );

/* Types used to define functions contained in the Ixxat .dll files */
typedef HRESULT (XATREG_CALLATTR *XAT_SelectHardwareType)( HWND , XAT_BoardCFG * );
typedef HRESULT (XATREG_CALLATTR *XAT_GetConfigType)( DWORD , XAT_BoardCFG * );
typedef HRESULT (XATREG_CALLATTR *XAT_GetDefaultHwEntryType)( DWORD * );
typedef INT32 (VCI_CALLATTR *VCI_StartCanType)( UINT16 , UINT8 );
typedef INT32 (VCI_CALLATTR *VCI_AssignRxQueObjType)( UINT16, UINT16, UINT8, UINT32, UINT32 );
typedef INT32 (VCI_CALLATTR *VCI_ConfigQueueType)( UINT16, UINT8, UINT8, UINT16, UINT16, UINT16, UINT16, UINT16* );
typedef INT32 (VCI_CALLATTR *VCI_SetAccMaskType)( UINT16, UINT8, UINT32, UINT32 );
typedef INT32 (VCI_CALLATTR *VCI_InitCanType)( UINT16, UINT8, UINT8, UINT8, UINT8 );
typedef INT32 (VCI_CALLATTR *VCI2_PrepareBoardType)( VCI_BOARD_TYPE, UINT16, char*, UINT8, VCI_t_PutS, VCI_t_UsrRxIntHdlr, VCI_t_UsrExcHdlr );
typedef INT32 (VCI_CALLATTR *VCI_CancelBoardType)( UINT16 );
typedef INT32 (VCI_CALLATTR *VCI_TransmitObjType)( UINT16, UINT16, UINT32, UINT8, UINT8* );
typedef INT32 (VCI_CALLATTR *VCI_RequestObjType)( UINT16, UINT16, UINT32, UINT8 );

/* local functions */
static const Error *InitLibrary( void );
static void UninitLibrary( void );

/* local data */
static VCI_t_UsrRxIntHdlr rxIntPtr[] = { rxInt0, rxInt1, rxInt2, rxInt3 };
#define MAX_BOARDS       sizeof(rxIntPtr)/sizeof(rxIntPtr[0])

static IxxatCAN *board[ MAX_BOARDS ] = {0};
static Mutex boardMutex;
static Mutex libraryMutex;
static int openCards = 0;

static HMODULE hReg;
static HINSTANCE hVCI;
static XAT_SelectHardwareType    lpXAT_SelectHardware;
static XAT_GetConfigType         lpXAT_GetConfig;
static XAT_GetDefaultHwEntryType lpXAT_GetDefaultHwEntry;
static VCI_StartCanType          lpVCI_StartCan;
static VCI_AssignRxQueObjType    lpVCI_AssignRxQueObj;
static VCI_ConfigQueueType       lpVCI_ConfigQueue;
static VCI_SetAccMaskType        lpVCI_SetAccMask;
static VCI_InitCanType           lpVCI_InitCan;
static VCI2_PrepareBoardType     lpVCI2_PrepareBoard;
static VCI_CancelBoardType       lpVCI_CancelBoard;
static VCI_TransmitObjType       lpVCI_TransmitObj;
static VCI_RequestObjType        lpVCI_RequestObj;

/***************************************************************************/
/**
Construct a new Ixxat CAN interface object.
This simply sets the default baud rate and 
marks the card as not open.
*/
/***************************************************************************/
IxxatCAN::IxxatCAN( void ) : CanInterface()
{
	// Default baud to 1,000,000 bps
	IxxatCAN::SetBaud( 1000000 );

	// Default to not open
	open = 0;
}

/***************************************************************************/
/**
Construct a new Ixxat CAN interface object for the specified port.

The port name should be of the form CANx or IXXATx where x is the port number.
The port numbers start at 0, so the first port would be identified by
the port name CAN0.

@param port The port name string identifying the CAN device.
*/
/***************************************************************************/
IxxatCAN::IxxatCAN( const char *port ) : CanInterface(port)
{
	// Default baud to 1,000,000 bps
	IxxatCAN::SetBaud( 1000000 );

	// Default to not open
	open = 0;
}

/***************************************************************************/
/**
Destructor for Ixxat card.  Closes the interface and unloads the library.
*/
/***************************************************************************/
IxxatCAN::~IxxatCAN(void)
{
	Close();
}

/***************************************************************************/
/**
Open the Ixxat CAN card.

The card should have been identified by setting it's name either
in the constructor, or by using the method CanInterface::SetName.

If no port name was set, then the default Ixxat card will be used.

If the port name is set to "select", then a dialog box will be shown
allowing the card to be selected from any installed Ixxat cards.

Otherwise, the port name should be of the form "CANx" where x is the
Ixxat hardware key number (i.e. CAN1 for hardware key 1).

@return A pointer to an error object on failure, or NULL on success.
*/
/***************************************************************************/
const Error *IxxatCAN::Open( void )
{
	int port;
	int ret = 0;

	mutex.Lock();

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

	/**************************************************
	* Find the port number to open.
	**************************************************/
	port = FindPortNumber( "CAN" );
	if( port < 0 ) 
		port = FindPortNumber( "IXXAT" );

	if( port < 0 )
	{
		mutex.Unlock();
		return &CanError::BadPortName;
	}

	const Error *err = InitLibrary();
	if( err )
	{
		cml.Error( "IxxatCAN::InitLibrary failed with error %s\n", err->toString() );
		mutex.Unlock();
		return err;
	}

	// Reset local variables
	rxHead = rxTail = 0;
	while( rxSem.Get(0) == 0 );

	/**************************************************
	* Find the board configuration info based on the
	* port name specified
	**************************************************/
	XAT_BoardCFG cfg;
	HRESULT res;
	DWORD key = port;
	int i = -1;

	if( port == 0 )
	{
		lpXAT_GetDefaultHwEntry( &key );
		res = lpXAT_GetConfig( key, &cfg );
	}

	else
		res = lpXAT_GetConfig( key, &cfg );

	if( res )
	{
		err = &CanError::BadPortName;
		goto done;
	}

	/**************************************************
	* Find an empty slot in the board array.
	**************************************************/
	boardMutex.Lock();
	for( i=0; i<MAX_BOARDS; i++ )
	{
		if( board[i] == NULL )
		{
			board[i] = this;
			break;
		}
	}
	boardMutex.Unlock();

	if( i == MAX_BOARDS )
	{
		i = -1;
		err = &CanError::Driver;
		goto done;
	}

	// For now, we always use channel 0.
	channel = 0;

	handle = lpVCI2_PrepareBoard( cfg.board_type, cfg.board_no, NULL, 0, 0, rxIntPtr[i], 0 );

	if( handle < 0 )
	{
		err = &CanError::Driver;
		goto done;
	}

	// initialize CAN-Controller
	ret = lpVCI_InitCan( handle, channel, bt0, bt1, VCI_11B );

	//  definition of Acceptance-Mask (define to receive all IDs)
	if( ret == VCI_OK ) 
		ret = lpVCI_SetAccMask( handle, channel, 0, 0 );

	//  definition of Transmit Queue
	if( ret == VCI_OK ) 
		ret = lpVCI_ConfigQueue( handle, channel, VCI_TX_QUE, 200, 0, 0, 0,  &txQueue );

	//  definition of Receive Queue (interrupt mode)
	if( ret == VCI_OK ) 
		ret = lpVCI_ConfigQueue( handle, channel, VCI_RX_QUE, 20, 1, 0, 100, &rxQueue );

	//  assign all ID's to the Receive Queue
	if( ret == VCI_OK ) 
		ret = lpVCI_AssignRxQueObj( handle, rxQueue, VCI_ACCEPT, 0, 0 );

	//  And now start the CAN
	if( ret == VCI_OK ) 
		ret = lpVCI_StartCan( handle, channel );

	if( ret != VCI_OK ) 
		err = ConvertError( ret );

done:

	if( err )
	{
		if( i >= 0 )
		{
			boardMutex.Lock();
			board[i] = NULL;
			boardMutex.Unlock();
		}
		UninitLibrary();
	}
	else
		open = 1;

	mutex.Unlock();

	return err;
}

/***************************************************************************/
/**
Close the CAN interface.
@return A pointer to an error object on failure, or NULL on success.
*/
/***************************************************************************/
const Error *IxxatCAN::Close( void )

⌨️ 快捷键说明

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