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();

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值