📄 can_vector.cpp
字号:
/************************************************************/
/* */
/* Copley Motion Libraries */
/* */
/* Author: Stephen Glow */
/* */
/* Copyright (c) 2002-2005 Copley Controls Corp. */
/* http://www.copleycontrols.com */
/* */
/************************************************************/
/* CAN object for Vector Can Card X */
#define DYNAMIC_CANDRIVER_DLL
#include <VCanD.h>
#include "CML.h"
#include <can_vector.h>
#include <windows.h>
#include <cstdio>
CML_NAMESPACE_USE();
/* local data - these are pointers to the functions defined in the Vector .dll file */
static const char *dllName = "vcand32.dll";
static HMODULE hDLL = 0;
static int openCards = 0;
static Mutex libraryMutex;
static NCDOPENDRIVER ncdDllOpenDriver;
static NCDCLOSEDRIVER ncdDllCloseDriver;
static NCDGETCHANNELMASK ncdGetChannelMask;
static NCDOPENPORT ncdOpenPort;
static NCDACTIVATECHANNEL ncdActivateChannel;
static NCDSETNOTIFICATION ncdSetNotification;
static NCDGETERRORSTRING ncdGetErrorString;
static NCDTRANSMIT ncdTransmit;
static NCDRECEIVE1 ncdReceive1;
static NCDRECEIVE ncdReceive;
static NCDREQUESTCHIPSTATE ncdRequestChipState;
static NCDSETCHANNELACCEPTANCE ncdSetChannelAcceptance;
static NCDDEACTIVATECHANNEL ncdDeactivateChannel;
static NCDCLOSEPORT ncdClosePort;
static NCDSETCHANNELBITRATE ncdSetChannelBitrate;
static NCDSETCHANNELMODE ncdSetChannelMode;
static NCDGETAPPLCONFIG ncdGetApplConfig;
static NCDRESETCLOCK ncdResetClock;
static NCDFLUSHRECEIVEQUEUE ncdFlushReceiveQueue;
static NCDGETEVENTSTRING ncdGetEventString;
static NCDSETAPPLCONFIG ncdSetApplConfig;
static NCDSETCHANNELPARAMS ncdSetChannelParams;
static NCDSETCHANNELPARAMSC200 ncdSetChannelParamsC200;
static NCDGETRECEIVEQUEUELEVEL ncdGetReceiveQueueLevel;
static NCDSETTIMERRATE ncdSetTimerRate;
static NCDGETDRIVERCONFIG ncdGetDriverConfig;
static NCDRESETACCEPTANCE ncdResetAcceptance;
static NCDADDACCEPTANCERANGE ncdAddAcceptanceRange;
static NCDREMOVEACCEPTANCERANGE ncdRemoveAcceptanceRange;
static NCDGETCHANNELINDEX ncdGetChannelIndex;
static NCDSETCHANNELOUTPUT ncdSetChannelOutput;
static NCDSETCHANNELTRANSCEIVER ncdSetChannelTransceiver;
static NCDFLUSHTRANSMITQUEUE ncdFlushTransmitQueue;
static NCDGETSTATE ncdGetState;
static NCDGETCHANNELVERSION ncdGetChannelVersion;
static NCDSETRECEIVEMODE ncdSetReceiveMode;
/* external functions */
extern const Error *WaitOnWindowsObject( HANDLE hndl, int32 timeout );
/* local data structure */
typedef struct
{
/// Event handle used to communicate events from the driver.
HANDLE event;
/// Mask used to identify the CAN channel to the driver
Vaccess mask;
/// Handle used to access the CAN port
VportHandle handle;
} LocalData;
/* local functions */
static const Error *ConvertError( Vstatus err );
static const Error *InitLibrary( void );
static void UninitLibrary( void );
/***************************************************************************/
/**
Construct a default CAN object.
The CAN interface is closed initially, and no port name is selected.
*/
/***************************************************************************/
VectorCAN::VectorCAN( void ) : CanInterface()
{
// Default baud to 1,000,000 bps
SetBaud( 1000000 );
// Default to not open
open = 0;
// Don't allow sharing
shareOK = false;
// Allocate memory for local data
data = new LocalData;
}
/***************************************************************************/
/**
Construct a CAN object with a specified port name.
The port name should be of the form CANx or VECTORx 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.
*/
/***************************************************************************/
VectorCAN::VectorCAN( const char *port ) : CanInterface(port)
{
// Default baud to 1,000,000 bps
baud = 1000000;
// Default to not open
open = 0;
// Don't allow sharing
shareOK = false;
// Allocate memory for local data
data = new LocalData;
}
/***************************************************************************/
/**
Close the CAN port and unload the dll.
*/
/***************************************************************************/
VectorCAN::~VectorCAN( void )
{
Close();
if( data ) delete data;
}
/***************************************************************************/
/**
Open the Vector CAN port.
@return A CAN error object identifying the error.
*/
/***************************************************************************/
const Error *VectorCAN::Open( void )
{
LocalData *ldat = (LocalData *)data;
int err;
int hwType, hwIndex, hwChannel;
int port;
if( !data )
return &CanError.Alloc;
mutex.Lock();
if( open )
{
mutex.Unlock();
return &CanError::AlreadyOpen;
}
/**************************************************
* Find the port number to open.
**************************************************/
port = FindPortNumber( "CAN" );
if( port < 0 )
port = FindPortNumber( "VECTOR" );
if( port < 0 )
{
mutex.Unlock();
return &CanError::BadPortName;
}
const Error *iniErr = InitLibrary();
if( iniErr )
{
cml.Error( "VectorCAN::InitLibrary failed with error: %s\n", iniErr->toString() );
mutex.Unlock();
return iniErr;
}
/**************************************************
* Open the driver.
**************************************************/
err = ncdDllOpenDriver();
/**************************************************
* Get a list of available CAN hardware
**************************************************/
int ct;
if( !err ) err = ncdGetDriverConfig( &ct, 0 );
if( !err && !ct ) err = VERR_HW_NOT_PRESENT;
if( !err )
{
VDriverConfig *cfg = new VDriverConfig[ ct ];
ncdGetDriverConfig( &ct, cfg );
int j;
for( j=0; j<cfg->channelCount; j++ )
{
// Ignore virtual channels
if( cfg->channel[j].hwType <= HWTYPE_VIRTUAL )
continue;
if( !port-- )
break;
}
if( j == cfg->channelCount )
err = VERR_HW_NOT_PRESENT;
else
{
hwType = cfg->channel[j].hwType;
hwIndex = cfg->channel[j].hwIndex;
hwChannel = cfg->channel[j].hwChannel;
}
delete cfg;
}
if( !err )
{
// Find the channel mask for this channel
ldat->mask = ncdGetChannelMask( hwType, hwIndex, hwChannel );
// If no mask was found, there is no such hardware available.
if( !ldat->mask )
err = VERR_HW_NOT_PRESENT;
}
Vaccess permission;
// Open the port
if( !err )
err = ncdOpenPort( &ldat->handle, "MotionLib", ldat->mask, ldat->mask, &permission, 1024 );
if( !err && !permission && !shareOK )
err = VERR_CHAN_IS_ONLINE;
// Set the channel baud rate
if( !err && permission )
err = ncdSetChannelBitrate( ldat->handle, ldat->mask, baud );
// Set normal output mode
if( !err && permission )
err = ncdSetChannelOutput( ldat->handle, ldat->mask, OUTPUT_MODE_NORMAL );
// Enable all messages
if( !err )
{
VsetAcceptance accept;
accept.code = 0;
accept.mask = 0;
err = ncdSetChannelAcceptance( ldat->handle, ldat->mask, &accept );
}
// Tell the port to notify me immediately if any data is received
if( !err )
{
ldat->event = CreateEvent( NULL, FALSE, FALSE, NULL );
err = ncdSetNotification( ldat->handle, (unsigned long *)&ldat->event, 1 );
}
// Reset the clock used to time events
if( !err )
err = ncdResetClock( ldat->handle );
// Disable the TX and TXRQ notifications
if( !err )
err = ncdSetChannelMode( ldat->handle, ldat->mask, 0, 0 );
if( !err )
err = ncdActivateChannel( ldat->handle, ldat->mask );
if( !err )
open = 1;
else
UninitLibrary();
mutex.Unlock();
return ConvertError(err);
}
/***************************************************************************/
/**
Close the CAN interface.
@return A CAN error object identifying the error.
*/
/***************************************************************************/
const Error *VectorCAN::Close( void )
{
LocalData *ldat = (LocalData *)data;
int err;
mutex.Lock();
if( !open )
{
return &CanError::NotOpen;
mutex.Unlock();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -