📄 can_kvaser.cpp
字号:
if( to < 0 )
to = 100;
else if( to > 100 )
{
to = 100;
timeout -= 100;
}
else
timeout = 0;
IncReadCount( 1 );
try {
status = LPcanReadWait( Handle, (long*)&frame.id, frame.data, &dlc, &flags, &time, to );
}
catch( ... ) {
IncReadCount( -1 );
throw;
}
IncReadCount( -1 );
if( status != canERR_NOMSG )
break;
}
}
if( status < 0 )
return ConvertError( status );
// indicate an extended frame by turning on bit 29 of the frame id
if( flags & canMSG_EXT )
{
frame.id &= 0x1FFFFFFF;
frame.id |= 0x20000000;
}
else
frame.id &= 0x000007FF;
// Log error flags
if( flags & canMSGERR_MASK )
cml.Warn( "Kvaser driver error: 0x%04x\n", flags );
// Set the frame type
if( flags & canMSG_ERROR_FRAME )
frame.type = CAN_FRAME_ERROR;
else if( flags & canMSG_RTR )
frame.type = CAN_FRAME_REMOTE;
else
frame.type = CAN_FRAME_DATA;
frame.length = dlc;
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, NULL on success.
*/
/***************************************************************************/
const Error *KvaserCAN::XmitFrame( CanFrame &frame, int32 timeout )
{
canStatus status;
long id;
uint dlc, flags;
// don't allow frame lengths longer than 8
if( frame.length > 8 )
return &CanError::BadParam;
id = frame.id & 0x1FFFFFFF;
dlc = frame.length;
switch( frame.type )
{
case CAN_FRAME_DATA:
flags = 0;
break;
case CAN_FRAME_REMOTE:
flags = canMSG_RTR;
break;
default:
return &CanError::BadParam;
}
// set the extended frame status
if( frame.id & 0x20000000 )
flags |= canMSG_EXT;
else
flags |= canMSG_STD;
mutex.Lock();
if( !open )
{
mutex.Unlock();
return &CanError::NotOpen;
}
status = LPcanWrite(Handle, id, frame.data, dlc, flags);
mutex.Unlock();
return ConvertError( status );
}
/***************************************************************************/
/**
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 on failure, NULL on success.
*/
/***************************************************************************/
const Error *KvaserCAN::ConvertError( int err )
{
switch( err )
{
case canOK: return 0;
case canERR_PARAM: return &CanError::BadPortName; // Error in parameter (correct?)
case canERR_NOMSG: return &CanError::Timeout; // No messages available (correct?)
case canERR_NOTFOUND: return &CanError::Driver; // Specified hw not found (more detail?)
case canERR_NOMEM: return &CanError::Driver; // Out of memory (more detail?)
case canERR_NOCHANNELS: return &CanError::BadPortName; // No channels avaliable
case canERR_RESERVED_3: return &CanError::Driver;
case canERR_TIMEOUT: return &CanError::Timeout; // Timeout ocurred
case canERR_NOTINITIALIZED: return &CanError::Driver; // Lib not initialized (more detail?)
case canERR_NOHANDLES: return &CanError::Driver; // Can't get handle (more detail?)
case canERR_INVHANDLE: return &CanError::Driver; // Handle is invalid (more detail?)
case canERR_INIFILE: return &CanError::Driver; // Error in the ini-file (16-bit only) (more detail?)
case canERR_DRIVER: return &CanError::Driver; // CAN driver type not supported
case canERR_TXBUFOFL: return &CanError::Driver; // Transmit buffer overflow
case canERR_RESERVED_1: return &CanError::Driver; // (more detail?)
case canERR_HARDWARE: return &CanError::Driver; // Some hardware error has occurred (more detail?)
case canERR_DYNALOAD: return &CanError::Driver; // Can't find requested DLL (more detail?)
case canERR_DYNALIB: return &CanError::Driver; // DLL seems to be wrong version (more detail?)
case canERR_DYNAINIT: return &CanError::Driver; // Error when initializing DLL
case canERR_RESERVED_4: return &CanError::Driver; // (more detail)
case canERR_RESERVED_5: return &CanError::Driver; // (more detail)
case canERR_RESERVED_6: return &CanError::Driver; // (more detail)
case canERR_RESERVED_2: return &CanError::Driver; // (more detail)
case canERR_DRIVERLOAD: return &CanError::Driver; // Can't find/load driver (more detail)
case canERR_DRIVERFAILED: return &CanError::Driver; // DeviceIOControl failed; use Win32 GetLastError() (more detail)
case canERR_NOCONFIGMGR: return &CanError::Driver; // Can't find req'd config s/w (e.g. CS/SS) (more detail)
case canERR_NOCARD: return &CanError::Driver; // The card was removed or not inserted (more detail)
case canERR_RESERVED_7: return &CanError::Driver;
case canERR_REGISTRY: return &CanError::Driver; // Error in the Registry (more detail)
case canERR_LICENSE: return &CanError::Driver; // The license is not valid. (more detail)
case canERR_INTERNAL: return &CanError::Driver; // Internal error in the driver. (more detail)
default:
return &CanError::Unknown;
}
}
/***************************************************************************/
/**
Increment the local read counter by the specified amount. The read counter
is used to keep track of how many threads are reading from the driver. This
allows me to exit the driver cleanly.
@param ct The amount to add to the read counter (normally 1 or -1)
*/
/***************************************************************************/
void KvaserCAN::IncReadCount( int ct )
{
readMutex.Lock();
readCount += ct;
readMutex.Unlock();
}
/***************************************************************************/
/**
Wait for the read counter to reach zero. This is used when the driver is
closed to ensure a clean exit.
*/
/***************************************************************************/
void KvaserCAN::WaitReadCount( void )
{
int ct;
while( 1 )
{
readMutex.Lock();
ct = readCount;
readMutex.Unlock();
if( ct <= 0 )
return;
Thread::sleep( 50 );
}
}
/***************************************************************************/
/**
Initialize the local pointers to the Kvaser .dll file.
@return A pointer to an error object or NULL on success
*/
/***************************************************************************/
static const Error *InitLibrary( void )
{
const Error *err = 0;
libraryMutex.Lock();
// Init the library for the first card only
if( !openCards )
{
// Load the Kvaser supplied .dll file
hDLL = LoadLibrary( dllName );
if( !hDLL )
{
cml.Error( "Unable to load library file: %s\n", dllName );
err = &CanError::NoDriver;
}
else
{
LPcanBusOn = (canBusOnType) GetProcAddress( hDLL, "canBusOn" );
LPcanSetBusParams = (canSetBusParamsType)GetProcAddress( hDLL, "canSetBusParams" );
LPcanIoCtl = (canIoCtlType) GetProcAddress( hDLL, "canIoCtl" );
LPcanOpenChannel = (canOpenChannelType) GetProcAddress( hDLL, "canOpenChannel" );
LPcanInitLibrary = (canInitLibraryType) GetProcAddress( hDLL, "canInitializeLibrary" );
LPcanClose = (canCloseType) GetProcAddress( hDLL, "canClose" );
LPcanBusOff = (canBusOffType) GetProcAddress( hDLL, "canBusOff" );
LPcanReadWait = (canReadWaitType) GetProcAddress( hDLL, "canReadWait" );
LPcanRead = (canReadType) GetProcAddress( hDLL, "canRead" );
LPcanWrite = (canWriteType) GetProcAddress( hDLL, "canWrite" );
if( !LPcanBusOn || !LPcanSetBusParams || !LPcanIoCtl ||
!LPcanOpenChannel || !LPcanInitLibrary || !LPcanClose ||
!LPcanBusOff || !LPcanReadWait || !LPcanRead || !LPcanWrite )
{
err = &CanError::NoDriver;
FreeLibrary( hDLL );
}
}
}
if( !err )
openCards++;
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( hDLL );
libraryMutex.Unlock();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -