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

📄 can_kvaser.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 KVASER CAN driver
   (see http://www.kvaser.com for more information on the KVASER driver for the PCIcanS card)
   */

#include <cstdio>
#include <errno.h>
#include <canlib.h>
#include "can_kvaser.h"
#include "CML.h"

/* external functions */
extern void CheckWindowsThreadStop( void );

/* Types used to define functions contained in the Kvaser .dll files */
typedef canStatus (CANLIBAPI *canBusOnType)( int );
typedef canStatus (CANLIBAPI *canSetBusParamsType)( int, long, uint, uint, uint, uint, uint );
typedef canStatus (CANLIBAPI *canIoCtlType)( int, uint, void*, uint );
typedef canStatus (CANLIBAPI *canOpenChannelType)( int, int );
typedef canStatus (CANLIBAPI *canInitLibraryType)( void );
typedef canStatus (CANLIBAPI *canCloseType)( int );
typedef canStatus (CANLIBAPI *canBusOffType)( int );
typedef canStatus (CANLIBAPI *canReadWaitType)( int, long*, void*, uint*, uint*, ulong*, ulong );
typedef canStatus (CANLIBAPI *canReadType)( int, long*, void*, uint*, uint*, ulong* );
typedef canStatus (CANLIBAPI *canWriteType)( int, long, void*, uint, uint );

CML_NAMESPACE_USE();

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

/* local data */
static const char *dllName = "canlib32.dll";
static HMODULE hDLL = 0;
static int openCards = 0;
static Mutex libraryMutex;

static canBusOnType LPcanBusOn;
static canSetBusParamsType LPcanSetBusParams;
static canIoCtlType LPcanIoCtl;
static canOpenChannelType LPcanOpenChannel;
static canInitLibraryType LPcanInitLibrary;
static canCloseType LPcanClose;
static canBusOffType LPcanBusOff;
static canReadWaitType LPcanReadWait;
static canReadType LPcanRead;
static canWriteType LPcanWrite;

/***************************************************************************/
/**
  Construct a default CAN object.
  The CAN interface is closed initially, and no port name is selected.
  */
/***************************************************************************/
KvaserCAN::KvaserCAN( void ) : CanInterface()
{
   // Default baud to 1,000,000 bps
   SetBaud( 1000000 );

   // Default to not open
   open = 0;
   readCount = 0;
}

/***************************************************************************/
/**
  Construct a CAN object with a specified port name.
  The port name should be of the form CANx or KVASERx 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.
  */
/***************************************************************************/
KvaserCAN::KvaserCAN( const char *port ) : CanInterface(port)
{
   // Default baud to 1,000,000 bps
   SetBaud( 1000000 );

   // Default to not open
   open = 0;
   readCount = 0;
}

/***************************************************************************/
/**
  Destructor.  This closes the CAN port and frees the .dll 
  */
/***************************************************************************/
KvaserCAN::~KvaserCAN( void ) 
{
   Close();
}

/***************************************************************************/
/**
  Open the Kvaser CAN port.  Before Open is called, the desired baud rate must
  have been specified by calling SetBaud, and the port name must have been
  set.  If the baud was not specified, it will default to 1,000,000 BPS.  If 
  the port name is not set, it will default to CAN0.

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

   mutex.Lock();

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

   /**************************************************
    * Find the port number to open.
    **************************************************/
   port = FindPortNumber( "CAN" );
   if( port < 0 ) port = FindPortNumber( "KVASER" );
   if( port < 0 )
   {
      mutex.Unlock();
      return &CanError::BadPortName;
   }

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

   LPcanInitLibrary();

   Handle = LPcanOpenChannel( port, canWANT_EXCLUSIVE);

   int status = LPcanIoCtl(Handle, canIOCTL_FLUSH_RX_BUFFER, NULL, NULL);

   // Set the baud rate 
   if( status == canOK ) status = LPcanSetBusParams(Handle, kvBaud, 0, 0, 0, 0, 0 );

   // Set the acceptance mask (not yet supported) ?
   if( status == canOK ) status = LPcanBusOn(Handle);
   open = 1;

   // Set the acceptance mask (not yet supported) ?
   mutex.Unlock();
   return ConvertError( status );
}

/***************************************************************************/
/**
  Close the CAN interface.
  @return A pointer to an error object on failure, NULL on success.
  */
/***************************************************************************/
const Error *KvaserCAN::Close( void )
{
   mutex.Lock();
   int wasOpen = open;
   open = 0;
   mutex.Unlock();

   if( !wasOpen )
      return 0;

   // Wait for reading threads to time out.
   WaitReadCount();

   mutex.Lock();
   canStatus status = LPcanBusOff(Handle);
   status = LPcanClose(Handle);
   mutex.Unlock();

   // Free the DLL if no longer in use.
   UninitLibrary();

   return ConvertError(status);
}


/***************************************************************************/
/**
  Set the CAN interface baud rate.
  @param b The baud rate to set.
  @return A pointer to an error object on failure, NULL on success.
  */
/***************************************************************************/
const Error *KvaserCAN::SetBaud( int32 b )
{
   switch( b )
   {
      case 1000000: kvBaud = BAUD_1M;   break;
      case  500000: kvBaud = BAUD_500K; break;
      case  250000: kvBaud = BAUD_250K; break;
      case  125000: kvBaud = BAUD_125K; break;
      case  100000: kvBaud = BAUD_100K; break;
      case   62000: kvBaud = BAUD_62K;  break;
      case   50000: kvBaud = BAUD_50K;  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, NULL on success.
  */
/***************************************************************************/
const Error *KvaserCAN::RecvFrame( CanFrame &frame, int32 timeout )
{
   canStatus       status;
   uint    dlc, flags;
   ulong   time;

   if( !open ) 
      return &CanError::NotOpen;

   // Do an immediate read if no timeout is requested
   if( timeout == 0 )
   {
      IncReadCount( 1 );
      try {
	 status = LPcanRead( Handle, (long*)&frame.id, frame.data, &dlc, &flags, &time );
      }
      catch( ... ) {
	 IncReadCount( -1 );
	 throw;
      }
      IncReadCount( -1 );
   }

   // For reading with a timeout, do a bunch of reads with a max timeout of 100 ms.
   // This allows me to check to make sure the thread wasn't stopped (Thread::stop)
   // while I was waiting.  This is kind of ugly, but it seems to be the only way 
   // to allow the thread to be stopped using this driver.
   else
   {
      while( timeout )
      {
	 if( !open ) 
	    return &CanError::NotOpen;

	 // Check for Thread::stop.
	 CheckWindowsThreadStop();

	 // Wait for up to 100 ms
	 int32 to = timeout;

⌨️ 快捷键说明

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