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

📄 can_vector.cpp

📁 美国COPLEY驱动器,程序开发工具之一.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/************************************************************/
/*                                                          */
/*  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 + -