我是靠谱客的博主 听话枫叶,最近开发中收集的这篇文章主要介绍Can通讯,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

好久没上来了,不久前有一个兄弟问我can通讯实现,这东西用了很久了,正好整理下资料,分享下。其实这个根据开发资料去做个简单demo还是很easy的,不过真实项目中使用,就应该注意处理通信中的性能,发送数据与接受数据都应该在线程中去处理。废话不多说,上干货。

准备:

  1. Can卡硬件有pci接口和usb接口的。pci性能上相对要更强,价格也贵很多,usb的性能上一般也能满足大多数通信需要,而且比较便宜,本例以usb接口为例;
  2. can通信相关资料,就以当前市面上最常见的产品为例,  hZLG致远电子-广州致远电子有限公司这里面有各种型号的硬件以及驱动下载;还有各种实现示例;
  3. 计算机连接can硬件,并安装好驱动;
  4. 所用的dll库为所提供资料中主要是调用ControlCAN.dll中的接口,将ControlCAN.dll和kerneldlls文件夹一起放入到自己工程中;

使用c++实现:

为了提高性能,一定要将can的发送和接受在线程中来实现;

封装can管理类CANManager

CANManager.h

class CANManager

{

private:

    CANManager(void);

public:

    ~CANManager(void);

    bool InitCan();

    bool CloseCan();

    void StartAllThread();

    void CloseAllThread();

    void SetCmdToQueue(VCI_CAN_OBJ* OBJ);

    void ReceiveMsgCan1();//接收CAN1消息

    bool SendCommandToCan1();//发送消息

    static CANManager * getInstance();

    static unsigned __stdcall SendTheardCAN1(LPVOID);

    static unsigned __stdcall RecvTheardCAN1(LPVOID);

private:

    bool m_bCanOpenSuc;

    bool m_bStartThread;

    CRITICAL_SECTION  lockQ1;

    HANDLE m_Rec1Thread;

    HANDLE m_Send1Thread;

    HANDLE m_hEventExitSend1;

    HANDLE m_hEventExitRecv1;

    std::queue<VCI_CAN_OBJ*> m_QSendCAN1; //CAN1发送队列

    ZLG *m_CAN1;

};

CANManager.cpp

CANManager::CANManager(void)

{

    m_bCanOpenSuc = false;

    m_bStartThread = false;

    InitializeCriticalSection(&lockQ1);

}

CANManager::~CANManager(void)

{

}

CANManager * CANManager::getInstance()

{

    static CANManager g_CANManager;

    return &g_CANManager;

}

//初始化CAN

bool CANManager::InitCan()

{

    CAN_PROPERTY_PARAM Init_PAram;//这个结构为什么这么赋值,请看资料,主要是配置can类型、索引、超时、模式、can通道以及波特率;

    Init_PAram.enUSBorPCI = USBCAN;

    Init_PAram.dwCANCardIndex = 0;

    Init_PAram.dwCANCardType = 21;

    Init_PAram.sendTimeout = 100;

    Init_PAram.mode = 0;

    Init_PAram.Baud.nBaudForPCICAN = 0x1C;

Init_PAram.Baud.nBaudForUSBCAN = 0x1C;

    //打开CAN1

    Init_PAram.dwCANChannelIndex = 0;

    m_CAN1 = new ZLG();

    m_CAN1->setCanProperty(Init_PAram);

    if (!m_CAN1->openDevice())

    {

        return false;

    }

    m_bCanOpenSuc = true;

    return true;

}

//关闭CAN

bool CANManager::CloseCan()

{

    if (!m_bCanOpenSuc){

        //already closed

        return true;

    }

    m_bCanOpenSuc = false;

    //关闭CAN

    if (!m_CAN1->closeDevice())

    {

        return false;

    }

    delete m_CAN1;

    m_CAN1 = NULL;

    return true;

}

void CANManager::StartAllThread()

{

    if (m_bCanOpenSuc)

    {

        m_bStartThread = true;

        m_hEventExitSend1 = CreateEvent(NULL, TRUE, TRUE, NULL);

        ResetEvent(m_hEventExitSend1);

        m_Send1Thread = (HANDLE)_beginthreadex(NULL, 0, CANManager::SendTheardCAN1, this, 0, 0);

        m_hEventExitRecv1 = CreateEvent(NULL, TRUE, TRUE, NULL);

        ResetEvent(m_hEventExitRecv1);

        m_Rec1Thread = (HANDLE)_beginthreadex(NULL, 0, CANManager::RecvTheardCAN1, this, 0, 0);

    }

}

void CANManager::CloseAllThread()

{

    if ((!m_bCanOpenSuc) || (!m_bStartThread)) {

        //already closed

        return;

    }

    m_bStartThread = false;

    if (WAIT_OBJECT_0 == WaitForSingleObject(m_hEventExitSend1, 500))

    {

        CloseHandle(m_Send1Thread);

        m_Send1Thread = INVALID_HANDLE_VALUE;

    }

    if (WAIT_OBJECT_0 == WaitForSingleObject(m_hEventExitRecv1, 500))

    {

        CloseHandle(m_Rec1Thread);

        m_Rec1Thread = INVALID_HANDLE_VALUE;

    }

    EnterCriticalSection(&lockQ1);

    while (!m_QSendCAN1.empty()) {

        delete m_QSendCAN1.front();

        m_QSendCAN1.pop();

    }

    LeaveCriticalSection(&lockQ1);

}

void CANManager::SetCmdToQueue(VCI_CAN_OBJ * OBJ)

{

    EnterCriticalSection(&lockQ1);

    m_QSendCAN1.push(OBJ);

    LeaveCriticalSection(&lockQ1);

}

//CAN1===============================================

unsigned __stdcall CANManager::SendTheardCAN1(LPVOID Owner)

{

    ((CANManager*)Owner)->SendCommandToCan1();

    return 0;

}

bool CANManager::SendCommandToCan1()

{

    while (m_bStartThread)

    {

        if (m_QSendCAN1.size() == 0)

        {

            Sleep(1);

        }

        else

        {

            //Sleep(1);

            EnterCriticalSection(&lockQ1);

            m_CAN1->transmit(m_QSendCAN1.front()->ID, m_QSendCAN1.front()->Data);

            delete m_QSendCAN1.front();

            m_QSendCAN1.pop();

            LeaveCriticalSection(&lockQ1);

        }

    }

    SetEvent(m_hEventExitSend1);

    return true;

}

unsigned __stdcall CANManager::RecvTheardCAN1(LPVOID Owner)

{

    ((CANManager*)Owner)->ReceiveMsgCan1();

    return 0;

}

void CANManager::ReceiveMsgCan1()

{

    int RecLength = 0;

    VCI_CAN_OBJ  RecOBJ[50];

    while (m_bStartThread) {

        RecLength = m_CAN1->receive(RecOBJ, 50, 100);//一次接受CAN消息最大个数

        if (RecLength <= 0) {

            Sleep(1);

            continue;

        }

        for (int i = 0; i < RecLength; ++i) {

            ControlManager::getInstance()->ReceiveCanMsg(RecOBJ[i]);

        }

    }

    SetEvent(m_hEventExitRecv1);

    return;

}

控制管理类ControlManager 依赖上个类

//ControlManager.h

class ControlManager

{

public:

    ControlManager(void);

    ~ControlManager(void);

    static ControlManager * getInstance();

    bool InitSC(std::string strCanType);

    bool sendCmdToDev();

    void ReceiveCanMsg(VCI_CAN_OBJ OBJ);

    void ExitSC();

private:

    void DecodeCANMsg(VCI_CAN_OBJ OBJ);

    CANManager * m_pCanManager;

};

//ControlManager.cpp

ControlManager::ControlManager(void)

{

    m_pCanManager = CANManager::getInstance();

}

ControlManager::~ControlManager(void)

{

}

ControlManager * ControlManager::getInstance()

{

    static ControlManager g_sSCManager;

    return &g_sSCManager;

}

bool ControlManager::InitSC()

{

    //初始化CAN口

    if (!m_pCanManager->InitCan())

    {        return false;

    }

writeInfoLog(0, "ControlManager::InitSC:", "init can Success!");

    //CAN打开成功,启动发送与接收线程

    m_pCanManager->StartAllThread();

    return true;

}

bool ControlManager::sendCmdToDev()

{

    VCI_CAN_OBJ* OBJ = new VCI_CAN_OBJ();

    //OBJ赋值....................根据发送接收协议进行赋值发送

    m_pCanManager->SetCmdToQueue(OBJ);//指令存入到CAN发送队列

    return true;

}

void ControlManager::ReceiveCanMsg(VCI_CAN_OBJ OBJ)//接收到CAN1 消息

{

    if (OBJ.Data == NULL){

        return;

    }

    DecodeCANMsg(OBJ);

}

void ControlManager::DecodeCANMsg(VCI_CAN_OBJ OBJ)

{

.....根据发送接收双方协议进行解析

}

void ControlManager::ExitSC()

{

    m_pCanManager->CloseAllThread();

    m_pCanManager->CloseCan();

}

架子已经搭好,就剩下如何封装can通讯接口了;

封装类ZLG 

ZLG.h:

typedef  struct  _VCI_CAN_OBJ_ZLG{ //帧结构

    UINT    ID;

    UINT    TimeStamp;

    BYTE    TimeFlag;

    BYTE    SendType;

    BYTE    RemoteFlag;//是否远程帧

    BYTE    ExternFlag;//是否扩展帧

    BYTE    DataLen;

    BYTE    Data[8];

    BYTE    Reserved[3];

}VCI_CAN_OBJ_ZLG,*PVCI_CAN_OBJ_ZLG;

//初始化数据类型

typedef struct _VCI_INIT_CONFIG_ZLG{

    DWORD    AccCode;

    DWORD    AccMask;

    DWORD    Reserved;

    UCHAR    Filter;

    UCHAR    Timing0;    

    UCHAR    Timing1;    

    UCHAR    Mode;

}VCI_INIT_CONFIG_ZLG,*PVCI_INIT_CONFIG_ZLG;

//接口卡信息的数据类型

typedef  struct  _VCI_BOARD_INFO_ZLG{

    USHORT    hw_Version;

    USHORT    fw_Version;

    USHORT    dr_Version;

    USHORT    in_Version;

    USHORT    irq_Num;

    BYTE    can_Num;

    CHAR    str_Serial_Num[20];

    CHAR    str_hw_Type[40];

    USHORT    Reserved[4];

} VCI_BOARD_INFO_ZLG,*PVCI_BOARD_INFO_ZLG;

enum USBCANorPCICAN//can接口类型

{

    USBCAN=1,

    PCICAN=2,

};

struct CAN_PROPERTY_PARAM//属性定义

{

    USBCANorPCICAN enUSBorPCI;

    DWORD dwCANCardType;

    DWORD dwCANCardIndex;

    DWORD dwCANChannelIndex;

    union unBaud

    {

        int nBaudForUSBCAN;

        int nBaudForPCICAN;

    }Baud;

    int mode;

    int sendTimeout;

};

class ZLG 

{

public:

    ZLG();

     ~ZLG();

     void setCanProperty(const CAN_PROPERTY_PARAM & SetProperty);

     BOOL openDevice();

     BOOL transmit(const UINT uInfoHead, const BYTE * pData, UINT ExternFlag = 0, UINT RemoteFlag = 0);

     UINT getReceiveNum();

     UINT receive(VCI_CAN_OBJ * pReceive, const ULONG Len, const INT WaitTime);

     BOOL closeDevice();

public:

    BOOL initCan();

    BOOL startCan();

    BOOL clearBuffer();

private:

    bool bSetProperty;

    bool bOpen;

    bool bClosed;

    HANDLE ghd_OneCanCardOnlyOpenOnce;  //防止重复打开

    HANDLE ghd_OneCanCardsOneChannelOnlyOpenOnce;//防止重复打开

    CAN_PROPERTY_PARAM m_CanProperty;

};

ZLG.cpp: initCan中的VCI_INIT_CONFIG字段mode如果测试可以设置为2,这样就是自发自收,便于测试;

const DWORD GCanBrTab[10] = {//波特率

0x060003, 0x060004, 0x060007,

0x1C0008, 0x1C0011, 0x160023,

0x1C002C, 0x1600B3, 0x1C00E0,

0x1C01C1

};

ZLG::ZLG() :bSetProperty(false),

bOpen(false),

bClosed(false),

ghd_OneCanCardOnlyOpenOnce(NULL),

ghd_OneCanCardsOneChannelOnlyOpenOnce(NULL)

{

}

ZLG::~ZLG()

{

if (!bClosed)

{

closeDevice();

}

if (ghd_OneCanCardOnlyOpenOnce != NULL)

{

CloseHandle(ghd_OneCanCardOnlyOpenOnce);

ghd_OneCanCardOnlyOpenOnce = NULL;

}

if (ghd_OneCanCardsOneChannelOnlyOpenOnce != NULL)

{

CloseHandle(ghd_OneCanCardsOneChannelOnlyOpenOnce);

ghd_OneCanCardsOneChannelOnlyOpenOnce = NULL;

}

}

void ZLG::setCanProperty(const CAN_PROPERTY_PARAM & SetProperty)

{

m_CanProperty = SetProperty;

bSetProperty = true;

}

BOOL ZLG::openDevice()

{

if (!bSetProperty)

{

return FALSE;

}

char HandleSTring[30];

sprintf_s(HandleSTring, "ThisCanCardIndex%d", m_CanProperty.dwCANCardIndex);

ghd_OneCanCardOnlyOpenOnce = CreateMutex(NULL, TRUE, HandleSTring);

if (GetLastError() == ERROR_ALREADY_EXISTS)

{

CloseHandle(ghd_OneCanCardOnlyOpenOnce);

ghd_OneCanCardOnlyOpenOnce = NULL;

if (!initCan())

{

bOpen = false;

return FALSE;

}

else

{

if (!startCan())

{

bOpen = false;

return FALSE;

}

else

{

if (!clearBuffer())

{

bOpen = false;

return FALSE;

}

else

{

bOpen = true;

BYTE byStartDataAny[8];

memset(byStartDataAny, 'X', 8);

if (!transmit(0, byStartDataAny))

{

bOpen = false;

return FALSE;

}

else

{

bOpen = true;

bClosed = false;

return TRUE;

}

}

}

}

}

else

{

if (STATUS_OK != VCI_OpenDevice(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex, m_CanProperty.mode))

{

bOpen = false;

return FALSE;

}

else

{

if (!initCan())

{

bOpen = false;

return FALSE;

}

else

{

if (!startCan())

{

bOpen = false;

return FALSE;

}

else

{

if (!clearBuffer())

{

bOpen = false;

return FALSE;

}

else

{

bOpen = true;

bClosed = false;

return TRUE;

}

}

}

}

}

}

BOOL ZLG::closeDevice()

{

if (ghd_OneCanCardOnlyOpenOnce != NULL)

{

CloseHandle(ghd_OneCanCardOnlyOpenOnce);

ghd_OneCanCardOnlyOpenOnce = NULL;

}

if (ghd_OneCanCardsOneChannelOnlyOpenOnce != NULL)

{

CloseHandle(ghd_OneCanCardsOneChannelOnlyOpenOnce);

ghd_OneCanCardsOneChannelOnlyOpenOnce = NULL;

}

VCI_CloseDevice(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex);

bClosed = true;

bOpen = false;

return TRUE;

}

BOOL TZLG::initCan()

{

char HandleSTring[50];

sprintf_s(HandleSTring, "ThisCanCardIndexChannelInd%d%d", m_CanProperty.dwCANCardIndex, m_CanProperty.dwCANChannelIndex);

ghd_OneCanCardsOneChannelOnlyOpenOnce = CreateMutex(NULL, TRUE, HandleSTring);

if (GetLastError() == ERROR_ALREADY_EXISTS)

{

CloseHandle(ghd_OneCanCardsOneChannelOnlyOpenOnce);

ghd_OneCanCardsOneChannelOnlyOpenOnce = NULL;

return FALSE;

}

else

{

if (PCICAN == m_CanProperty.enUSBorPCI)

{

VCI_INIT_CONFIG init_config;

init_config.AccCode = 0;

init_config.AccMask = 0xffffffff;

init_config.Filter = 0;

init_config.Mode = 0;//此字段如果设置为2 就可以自发自收,便于测试

init_config.Timing0 = 0;

init_config.Timing1 = m_CanProperty.Baud.nBaudForPCICAN;

if (STATUS_OK != VCI_InitCAN(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex, m_CanProperty.dwCANChannelIndex, &init_config))

{

return FALSE;

}

else

{

return TRUE;

}

}

else if (USBCAN == m_CanProperty.enUSBorPCI)

{

DWORD band = GCanBrTab[2];

if (VCI_SetReference(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex, 0, 0, &band) != STATUS_OK)

{

return FALSE;

}

VCI_INIT_CONFIG init_config;

init_config.AccCode = 0;

init_config.AccMask = 0xffffffff;

init_config.Filter = 0;

init_config.Mode = 0;

init_config.Timing0 = 0;

init_config.Timing1 = m_CanProperty.Baud.nBaudForUSBCAN;

if (STATUS_OK != VCI_InitCAN(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex, m_CanProperty.dwCANChannelIndex, &init_config))

{

return FALSE;

}

else

{

return TRUE;

}

}

}

return FALSE;

}

BOOL ZLG::startCan()

{

if (STATUS_OK != VCI_StartCAN(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex, m_CanProperty.dwCANChannelIndex))

{

return FALSE;

}

else

{

return TRUE;

}

}

BOOL ZLG::clearBuffer()

{

if (STATUS_OK != VCI_ClearBuffer(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex, m_CanProperty.dwCANChannelIndex))

{

return FALSE;

}

else

{

return TRUE;

}

}

BOOL ZLG::transmit(const UINT uInfoHead, const BYTE * pData, UINT ExternFlag, UINT RemoteFlag)

{

if (!bOpen || pData == NULL)

{

return FALSE;

}

VCI_CAN_OBJ frameinfo;

frameinfo.ID = uInfoHead;

frameinfo.DataLen = 8;

frameinfo.ExternFlag = ExternFlag;    //0:标准帧, 1:扩展帧

frameinfo.RemoteFlag = RemoteFlag;    //0:数据帧, 1:远程帧

frameinfo.SendType = 0;

memcpy(frameinfo.Data, pData, frameinfo.DataLen);

DWORD ask = VCI_SetReference(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex, m_CanProperty.dwCANChannelIndex, 3, &m_CanProperty.sendTimeout);

DWORD ask_transmit = VCI_Transmit(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex, m_CanProperty.dwCANChannelIndex, &frameinfo, 1);

if (ask_transmit != STATUS_OK)

{

return FALSE;

}

return TRUE;

}

UINT ZLG::getReceiveNum()

{

if (!bOpen)

{

return 0;

}

VCI_ERR_INFO errinfo;

ULONG RecvNum = 0;

RecvNum = VCI_GetReceiveNum(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex, m_CanProperty.dwCANChannelIndex);

if (RecvNum <= 0)

{

VCI_ReadErrInfo(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex, m_CanProperty.dwCANChannelIndex, &errinfo);

}

return RecvNum;

}

UINT ZLG::receive(VCI_CAN_OBJ* pReceive, const ULONG Len, const INT WaitTime)

{

if (!bOpen)

{

return 0;

}

ULONG Rlen = 0;

VCI_ERR_INFO errinfo;

Rlen = VCI_Receive(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex, m_CanProperty.dwCANChannelIndex, pReceive, Len, WaitTime);

if (Rlen < 0)

{

VCI_ReadErrInfo(m_CanProperty.dwCANCardType, m_CanProperty.dwCANCardIndex, 0, &errinfo);

}

return Rlen;

}

厂商提供的接口头文件

//接口卡类型定义

#define VCI_PCI5121        1

#define VCI_PCI9810        2

#define VCI_USBCAN1        3

#define VCI_USBCAN2        4

#define VCI_USBCAN2A    4

#define VCI_PCI9820        5

#define VCI_CAN232        6

#define VCI_PCI5110        7

#define VCI_CANLITE        8

#define VCI_ISA9620        9

#define VCI_ISA5420        10

#define VCI_PC104CAN    11

#define VCI_CANETUDP    12

#define VCI_CANETE        12

#define VCI_DNP9810        13

#define VCI_PCI9840        14

#define VCI_PC104CAN2    15

#define VCI_PCI9820I    16

#define VCI_CANETTCP    17

#define VCI_PEC9920        18

#define VCI_PCIE_9220    18

#define VCI_PCI5010U    19

#define VCI_USBCAN_E_U    20

#define VCI_USBCAN_2E_U 21

#define VCI_PCI5020U    22

#define VCI_EG20T_CAN    23

#define VCI_PCIE9221    24

//CAN错误码

#define    ERR_CAN_OVERFLOW            0x0001    //CAN控制器内部FIFO溢出

#define    ERR_CAN_ERRALARM            0x0002    //CAN控制器错误报警

#define    ERR_CAN_PASSIVE                0x0004    //CAN控制器消极错误

#define    ERR_CAN_LOSE                0x0008    //CAN控制器仲裁丢失

#define    ERR_CAN_BUSERR                0x0010    //CAN控制器总线错误

#define ERR_CAN_BUSOFF                0x0020 //总线关闭错误

//通用错误码

#define    ERR_DEVICEOPENED            0x0100    //设备已经打开

#define    ERR_DEVICEOPEN                0x0200    //打开设备错误

#define    ERR_DEVICENOTOPEN            0x0400    //设备没有打开

#define    ERR_BUFFEROVERFLOW            0x0800    //缓冲区溢出

#define    ERR_DEVICENOTEXIST            0x1000    //此设备不存在

#define    ERR_LOADKERNELDLL            0x2000    //装载动态库失败

#define ERR_CMDFAILED                0x4000    //执行命令失败错误码

#define    ERR_BUFFERCREATE            0x8000    //内存不足

//函数调用返回状态值

#define    STATUS_OK                    1

#define STATUS_ERR                    0

    

#define CMD_DESIP            0

#define CMD_DESPORT            1

#define CMD_CHGDESIPANDPORT        2

#define CMD_SRCPORT            2        

#define CMD_TCP_TYPE        4                    //tcp 工作方式,服务器:1 或是客户端:0

#define TCP_CLIENT            0

#define TCP_SERVER            1

//服务器方式下有效

#define CMD_CLIENT_COUNT    5                    //连接上的客户端计数

#define CMD_CLIENTS            6                    //连接上的客户端

#define CMD_DISCONN_CLINET  7                    //断开一个连接

typedef struct tagRemoteClient{

    int iIndex;

    DWORD port;

    HANDLE hClient;

    char szip[32];

}REMOTE_CLIENT;

//1.ZLGCAN系列接口卡信息的数据类型。

typedef  struct  _VCI_BOARD_INFO{

        USHORT    hw_Version;

        USHORT    fw_Version;

        USHORT    dr_Version;

        USHORT    in_Version;

        USHORT    irq_Num;

        BYTE    can_Num;

        CHAR    str_Serial_Num[20];

        CHAR    str_hw_Type[40];

        USHORT    Reserved[4];

} VCI_BOARD_INFO,*PVCI_BOARD_INFO;

//2.定义CAN信息帧的数据类型。

typedef  struct  _VCI_CAN_OBJ{

    UINT    ID;

    UINT    TimeStamp;

    BYTE    TimeFlag;

    BYTE    SendType;

    BYTE    RemoteFlag;//是否是远程帧

    BYTE    ExternFlag;//是否是扩展帧

    BYTE    DataLen;

    BYTE    Data[8];

    BYTE    Reserved[3];

}VCI_CAN_OBJ,*PVCI_CAN_OBJ;

//3.定义CAN控制器状态的数据类型。

typedef struct _VCI_CAN_STATUS{

    UCHAR    ErrInterrupt;

    UCHAR    regMode;

    UCHAR    regStatus;

    UCHAR    regALCapture;

    UCHAR    regECCapture;

    UCHAR    regEWLimit;

    UCHAR    regRECounter;

    UCHAR    regTECounter;

    DWORD    Reserved;

}VCI_CAN_STATUS,*PVCI_CAN_STATUS;

//4.定义错误信息的数据类型。

typedef struct _VCI_ERR_INFO{

        UINT    ErrCode;

        BYTE    Passive_ErrData[3];

        BYTE    ArLost_ErrData;

} VCI_ERR_INFO,*PVCI_ERR_INFO;

//5.定义初始化CAN的数据类型

typedef struct _VCI_INIT_CONFIG{

    DWORD    AccCode;

    DWORD    AccMask;

    DWORD    Reserved;

    UCHAR    Filter;

    UCHAR    Timing0;    

    UCHAR    Timing1;    

    UCHAR    Mode;

}VCI_INIT_CONFIG,*PVCI_INIT_CONFIG;

typedef struct _tagChgDesIPAndPort

{

    char szpwd[10];

    char szdesip[20];

    int desport;

    BYTE blistenonly;

}CHGDESIPANDPORT;

/ new add struct for filter /

typedef struct _VCI_FILTER_RECORD{

    DWORD ExtFrame;    //是否为扩展帧

    DWORD Start;

    DWORD End;

}VCI_FILTER_RECORD,*PVCI_FILTER_RECORD;

#define EXTERNC        extern "C"

EXTERNC DWORD __stdcall VCI_OpenDevice(DWORD DeviceType,DWORD DeviceInd,DWORD Reserved);

EXTERNC DWORD __stdcall VCI_CloseDevice(DWORD DeviceType,DWORD DeviceInd);

EXTERNC DWORD __stdcall VCI_InitCAN(DWORD DeviceType, DWORD DeviceInd, DWORD CANInd, PVCI_INIT_CONFIG pInitConfig);

EXTERNC DWORD __stdcall VCI_ReadBoardInfo(DWORD DeviceType,DWORD DeviceInd,PVCI_BOARD_INFO pInfo);

EXTERNC DWORD __stdcall VCI_ReadErrInfo(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_ERR_INFO pErrInfo);

EXTERNC DWORD __stdcall VCI_ReadCANStatus(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_STATUS pCANStatus);

EXTERNC DWORD __stdcall VCI_GetReference(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,DWORD RefType,PVOID pData);

EXTERNC DWORD __stdcall VCI_SetReference(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,DWORD RefType,PVOID pData);

EXTERNC ULONG __stdcall VCI_GetReceiveNum(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);

EXTERNC DWORD __stdcall VCI_ClearBuffer(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);

EXTERNC DWORD __stdcall VCI_StartCAN(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);

EXTERNC DWORD __stdcall VCI_ResetCAN(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);

EXTERNC ULONG __stdcall VCI_Transmit(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_OBJ pSend,ULONG Len);

EXTERNC ULONG __stdcall VCI_Receive(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_OBJ pReceive,ULONG Len,INT WaitTime=-1);

搞定!

最后

以上就是听话枫叶为你收集整理的Can通讯的全部内容,希望文章能够帮你解决Can通讯所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(58)

评论列表共有 0 条评论

立即
投稿
返回
顶部