本章将介绍Vector XL设备驱动库DLL的使用,XL设备驱动库可以驱动Vector旗下的任何一种CAN设备,我们可以利用该设备驱动实现CAN总线上报文的收发,其官方驱动库的下载地址如下所示:
https://www.vector.com/int/en/products/products-a-z/libraries-drivers/xl-driver-library/#c75493
本文对XL驱动库例程中的xlCANdemo的代码进行了一层抽象,其头文件为VectorXLDriver.h,其内容如下所示:
#ifndef __VECTORXLDRIVER_H
#define __VECTORXLDRIVER_H
#define DYNAMIC_XLDRIVER_DLL
#define DO_NOT_DEFINE_EXTERN_DECLARATION
#include "vxlapi.h"
#define RECEIVE_EVENT_SIZE 1 // DO NOT EDIT! Currently 1 is supported only
#define RX_QUEUE_SIZE 4096 // internal driver queue size in CAN events
typedef struct
{
uint8_t channelIndex;
uint64_t channelMask;
char name[31];
uint32_t channelBusCapabilities;
uint32_t channelCapabilities;
}VectorDriverChannel;
typedef struct
{
VectorDriverChannel channel[31];
int channelNum;
}VectorDriverChannelManage;
extern uint32_t uiSelectChannelConfigIndex;
extern uint32_t uiCanBaudrate;//1M
extern VectorDriverChannelManage vectorDriverChannelConfig;
int VectorXLDriverDllLoad(void);
int VectorXLDriverDllUnLoad(void);
int VectorDeviceInit(void);
int VectorDeviceUnInit(void);
int VectorDeviceChannelConfig(void);
int VectorDeviceRx(int *externFrame,int *id,int *dataLen,uint8_t *data);
int VectorDeviceTx(int externFrame,int id,int dataLen,uint8_t *data);
#endif
其VectorXLDriver.c代码如下所示:
#include <windows.h>
#include <ansi_c.h>
#include <utility.h>
#include "VectorXLDriver.h"
HMODULE vxlDllHandle = 0;
XLOPENDRIVER xlOpenDriver;
XLCLOSEDRIVER xlCloseDriver;
XLOPENPORT xlOpenPort;
XLCLOSEPORT xlClosePort;
XLGETDRIVERCONFIG xlGetDriverConfig;
XLACTIVATECHANNEL xlActivateChannel;
XLDEACTIVATECHANNEL xlDeactivateChannel;
XLCANRECEIVE xlCanReceive;
XLRECEIVE xlReceive;
XLCANTRANSMIT xlCanTransmit;
XLCANTRANSMITEX xlCanTransmitEx;
XLCANFDSETCONFIGURATION xlCanFdSetConfiguration;
XLCANSETCHANNELPARAMS xlCanSetChannelBitrate;
XLGETERRORSTRING xlGetErrorString;
XLCANGETEVENTSTRING xlCanGetEventString;
XLGETEVENTSTRING xlGetEventString;
XLSETNOTIFICATION xlSetNotification;
uint32_t openDriverFlag = 0;
uint32_t channelActiveFlag = 0;
uint32_t openPortFlag = 0;
//UI config value
uint32_t uiSelectChannelConfigIndex = 0;
uint32_t uiCanBaudrate = 1000000;//1M
char g_AppName[XL_MAX_LENGTH+1] = "xlCANdemo"; //!< Application name which is displayed in VHWconf
XLportHandle g_xlPortHandle = XL_INVALID_PORTHANDLE; //!< Global porthandle (we use only one!)
XLdriverConfig g_xlDrvConfig; //!< Contains the actual hardware configuration
XLaccess g_xlChannelMask = 0; //!< Global channelmask (includes all founded channels)
XLaccess g_xlPermissionMask = 0; //!< Global permissionmask (includes all founded channels)
unsigned int g_canFdSupport = 0; //!< Global CAN FD support flag
VectorDriverChannelManage vectorDriverChannelConfig;
int VectorXLDriverDllLoad(void)
{
vxlDllHandle = LoadLibrary(".\\vxlapi.dll");
if(vxlDllHandle != NULL)
{
printf("LoadLibrary Successful\r\n");
xlOpenDriver = GetProcAddress(vxlDllHandle,"xlOpenDriver");
xlCloseDriver = GetProcAddress(vxlDllHandle,"xlCloseDriver");
xlGetDriverConfig = GetProcAddress(vxlDllHandle,"xlGetDriverConfig");
xlOpenPort = GetProcAddress(vxlDllHandle,"xlOpenPort");
xlClosePort = GetProcAddress(vxlDllHandle,"xlClosePort");
xlActivateChannel = GetProcAddress(vxlDllHandle,"xlActivateChannel");
xlDeactivateChannel = GetProcAddress(vxlDllHandle,"xlDeactivateChannel");
xlCanTransmit = GetProcAddress(vxlDllHandle,"xlCanTransmit");
xlCanTransmitEx = GetProcAddress(vxlDllHandle,"xlCanTransmitEx");
xlCanReceive = GetProcAddress(vxlDllHandle,"xlCanReceive");
xlCanFdSetConfiguration = GetProcAddress(vxlDllHandle,"xlCanFdSetConfiguration");
xlCanSetChannelBitrate = GetProcAddress(vxlDllHandle,"xlCanSetChannelBitrate");
xlSetNotification = GetProcAddress(vxlDllHandle,"xlSetNotification");
xlCanGetEventString = GetProcAddress(vxlDllHandle,"xlCanGetEventString");
xlGetEventString = GetProcAddress(vxlDllHandle,"xlGetEventString");
xlGetErrorString = GetProcAddress(vxlDllHandle,"xlGetErrorString");
return 0;
}
else
{
return -1;
}
}
int VectorXLDriverDllUnLoad(void)
{
if(vxlDllHandle != NULL)
{
FreeLibrary(vxlDllHandle);
}
return 0;
}
int VectorDeviceInit(void)
{
XLstatus xlStatus;
int i,j;
vectorDriverChannelConfig.channelNum = 0;
xlStatus = xlOpenDriver ();
if(XL_SUCCESS != xlStatus)
{
return -1;
}
openDriverFlag = 1;
xlStatus = xlGetDriverConfig(&g_xlDrvConfig);
if(XL_SUCCESS != xlStatus)
{
return -1;
}
for (i=0,j=0; i < g_xlDrvConfig.channelCount; i++)
{
// we take all hardware we found and supports CAN
if (g_xlDrvConfig.channel[i].channelBusCapabilities & XL_BUS_ACTIVE_CAP_CAN)
{
//收集CAN可配置通道信息
vectorDriverChannelConfig.channel[j].channelBusCapabilities = g_xlDrvConfig.channel[i].channelBusCapabilities;
vectorDriverChannelConfig.channel[j].channelCapabilities = g_xlDrvConfig.channel[i].channelCapabilities;
vectorDriverChannelConfig.channel[j].channelIndex = g_xlDrvConfig.channel[i].channelIndex;
vectorDriverChannelConfig.channel[j].channelMask = g_xlDrvConfig.channel[i].channelMask;
strcpy(vectorDriverChannelConfig.channel[j].name,g_xlDrvConfig.channel[i].name);
vectorDriverChannelConfig.channelNum = ++j;
}
}
return 0;
}
int VectorDeviceChannelConfig(void)
{
XLstatus xlStatus;
XLaccess xlChannelMaskFd = 0;
int i,j;
if(vectorDriverChannelConfig.channelNum == 0)
return -1;
if((vectorDriverChannelConfig.channel[uiSelectChannelConfigIndex].channelCapabilities & XL_CHANNEL_FLAG_CANFD_ISO_SUPPORT) > 0)
{
g_canFdSupport = 1;
}
else
{
}
g_xlChannelMask = vectorDriverChannelConfig.channel[uiSelectChannelConfigIndex].channelMask;
g_xlPermissionMask = g_xlChannelMask;
if (g_canFdSupport)
{
xlStatus = xlOpenPort(&g_xlPortHandle, g_AppName, g_xlChannelMask, &g_xlPermissionMask, 16000, XL_INTERFACE_VERSION_V4, XL_BUS_TYPE_CAN);
}
// if not, we make 'normal' CAN
else
{
xlStatus = xlOpenPort(&g_xlPortHandle, g_AppName, g_xlChannelMask, &g_xlPermissionMask, RX_QUEUE_SIZE, XL_INTERFACE_VERSION, XL_BUS_TYPE_CAN);
}
if(XL_SUCCESS != xlStatus)
{
return -1;
}
openPortFlag = 1;
if(XL_INVALID_PORTHANDLE != g_xlPortHandle)
{
if(g_canFdSupport)
{
XLcanFdConf fdParams;
memset(&fdParams, 0, sizeof(fdParams));
// arbitration bitrate
fdParams.arbitrationBitRate = uiCanBaudrate;
fdParams.tseg1Abr = 6;
fdParams.tseg2Abr = 3;
fdParams.sjwAbr = 2;
// data bitrate
fdParams.dataBitRate = fdParams.arbitrationBitRate*2;
fdParams.tseg1Dbr = 6;
fdParams.tseg2Dbr = 3;
fdParams.sjwDbr = 2;
xlStatus = xlCanFdSetConfiguration(g_xlPortHandle, g_xlChannelMask, &fdParams);
if(XL_SUCCESS != xlStatus)
{
return -1;
}
}
else
{
xlStatus = xlCanSetChannelBitrate(g_xlPortHandle, g_xlChannelMask, uiCanBaudrate);
if(XL_SUCCESS != xlStatus)
{
return -1;
}
}
}
xlStatus = xlActivateChannel(g_xlPortHandle, g_xlChannelMask, XL_BUS_TYPE_CAN, XL_ACTIVATE_RESET_CLOCK);
if(XL_SUCCESS != xlStatus)
{
return -1;
}
channelActiveFlag = 1;
return 0;
}
int VectorDeviceUnInit(void)
{
if(channelActiveFlag > 0)
{
xlDeactivateChannel(g_xlPortHandle, g_xlChannelMask);
channelActiveFlag = 0;
}
if(openPortFlag > 0)
{
xlClosePort(g_xlPortHandle);
openPortFlag = 0;
}
if(openDriverFlag > 0)
{
xlCloseDriver();
openDriverFlag = 0;
}
return 0;
}
int VectorDeviceRx(int *externFrame,int *id,int *dataLen,uint8_t *data)
{
XLstatus xlStatus;
XLcanRxEvent xlCanRxEvt;
int i,frameDataLen;
unsigned char *frameData;
xlStatus = xlCanReceive(g_xlPortHandle, &xlCanRxEvt);
if(xlStatus != XL_ERR_QUEUE_IS_EMPTY )
{
if(xlCanRxEvt.tag != XL_CAN_EV_TAG_RX_OK)
return -1;
if((xlCanRxEvt.tagData.canRxOkMsg.canId & XL_CAN_EXT_MSG_ID) > 0)
{
*externFrame = 1;
*id = xlCanRxEvt.tagData.canRxOkMsg.canId & (~XL_CAN_EXT_MSG_ID);
}
else
{
*externFrame = 0;
*id = xlCanRxEvt.tagData.canRxOkMsg.canId;
}
*dataLen = xlCanRxEvt.tagData.canRxOkMsg.dlc;
frameDataLen = xlCanRxEvt.tagData.canRxOkMsg.dlc;
frameData = &xlCanRxEvt.tagData.canRxOkMsg.data[0];
for(i=0;i<frameDataLen;i++)
{
data[i] = frameData[i];
}
return 0;
}
else
{
return -1;
}
}
int VectorDeviceTx(int externFrame,int id,int dataLen,uint8_t *data)
{
XLstatus xlStatus;
unsigned int cntSent;
int i,frameDataLen;
unsigned char *frameData;
unsigned int messageCount = 1;
if(g_canFdSupport)
{
XLcanTxEvent canTxEvt;
memset(&canTxEvt, 0, sizeof(canTxEvt));
canTxEvt.tag = XL_CAN_EV_TAG_TX_MSG;
canTxEvt.transId = 0xFFFF;
if(externFrame > 0)
{
canTxEvt.tagData.canMsg.canId = id | XL_CAN_EXT_MSG_ID;
}
else
{
canTxEvt.tagData.canMsg.canId = id;
}
canTxEvt.tagData.canMsg.msgFlags = 0;//CAN2.0
frameDataLen = dataLen;
canTxEvt.tagData.canMsg.dlc = dataLen;
frameData = canTxEvt.tagData.canMsg.data;
for(i=0;i<frameDataLen;i++)
{
frameData[i] = data[i];
}
g_xlChannelMask = 1 << (17 - 1);
xlStatus = xlCanTransmitEx(g_xlPortHandle, g_xlChannelMask, messageCount, &cntSent, &canTxEvt);
}
else
{
XLevent xlEvent;
memset(&xlEvent, 0, sizeof(xlEvent));
xlEvent.tag = XL_TRANSMIT_MSG;
xlEvent.tagData.msg.id = id;
xlEvent.tagData.msg.flags = 0;
xlEvent.tagData.msg.dlc = dataLen;
frameData = xlEvent.tagData.msg.data;
for(i=0;i<frameDataLen;i++)
{
frameData[i] = data[i];
}
xlStatus = xlCanTransmit(g_xlPortHandle, g_xlChannelMask, &messageCount, &xlEvent);
}
return 0;
}
驱动使用:
在使用本章抽象代码之前,需要先调用VectorXLDriverDllLoad加载vxlapi.dll驱动函数,然后调用VectorDeviceInit获得满足CAN通道的数组vectorDriverChannelConfig,然后通过UI界面选择CAN通道(uiSelectChannelConfigIndex)和CAN波特率(uiCanBaudrate),然后调用VectorDeviceChannelConfig配置CAN通道,最后就可以调用VectorDeviceRx和VectorDeviceTx进行报文的收发。当程序退出时,记得调用VectorDeviceUnInit和VectorXLDriverDllUnLoad。