PCAN的使用简单demo

参考   PCAN示例资源文件介绍:PCAN示例资源文件介绍 - GitCode

安装驱动  https://www.peak-system.com/produktcd/Drivers/PeakOemDrv.exe

无脑下一步就行

 

此处就是界面上添加了一个 按钮,用于创建连接,界面代码自己简单做一个

pro中添加  serialbus

QT       += serialbus

 

.h

复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QCanBusDevice>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    //std::unique_ptr<QCanBusDevice> m_canDevice;
    QCanBusDevice *m_canDevice=nullptr;
    QList<QCanBusDeviceInfo> m_interfaces;
    short tacomathrottle;
    short tacomasteer;
    short tacomaspeed;
    bool tacomabrake;
private slots:
    void processReceivedFrames();
    void processErrors(QCanBusDevice::CanBusError) const;
    void canconnectclicked();
};
#endif // MAINWINDOW_H
复制代码

 

.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
#include <QCanBus>
#include <QDebug>
#include <QCanBusFrame>
#include <QTimer>
 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    connect(ui->canBT,&QPushButton::clicked,this,&MainWindow::canconnectclicked);
 
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
void MainWindow::processErrors(QCanBusDevice::CanBusError error) const
{
    switch (error) {
    case QCanBusDevice::ReadError:
    case QCanBusDevice::WriteError:
    case QCanBusDevice::ConnectionError:
    case QCanBusDevice::ConfigurationError:
    case QCanBusDevice::UnknownError:
        qDebug()<<m_canDevice->errorString();
        break;
    default:
        break;
    }
}
 
void MainWindow::processReceivedFrames()
{
    if (!m_canDevice)
        return;
 
    while (m_canDevice->framesAvailable())
    {
        const QCanBusFrame frame = m_canDevice->readFrame();
        //qDebug()<<frame.error();
        // qDebug()<<frame.frameId();//frame id,it's decimal
        //qDebug()<<frame.frameType();//1 means dataframe
        //qDebug()<<m_canDevice->state();
 
        QString view;
        if (frame.frameType() == QCanBusFrame::ErrorFrame)
        {
            view = m_canDevice->interpretErrorFrame(frame);
        }
        else if(frame.frameType()==QCanBusFrame::DataFrame)
        {
            view=frame.toString();
        }
        qDebug()<<view;
 
    }
}
 
 
void MainWindow::canconnectclicked()
{
    //QCanBus::instance()->plugins();
    const QString plugin="peakcan";
    int bitrate=500000;
    bitrate=125000;
    bool connectflag=false;
    QString errorString;
 
 
    //const QString plugin="virtualcan";
    // qDebug()<< QCanBus::instance()->plugins();
    m_interfaces = QCanBus::instance()->availableDevices(plugin);
    if(!m_interfaces.empty())
    {
        qDebug()<<m_interfaces.begin()->name();
        m_canDevice=QCanBus::instance()->createDevice(plugin, m_interfaces.begin()->name(), &errorString);
    }
    else
    {
        qDebug()<<"do not find available interface for pcan";
    }
 
    if (!m_canDevice)
    {
        qDebug() <<"createDevice error" <<errorString;
    }
    else
    {
        /***peakcan do not support configuration key RawFilterKey***/
        //        QCanBusDevice::Filter filter;
        //        QList<QCanBusDevice::Filter> filterList;
        //        // filter all CAN bus packages with id 0x444 (base) or 0xXXXXX444 (extended)
        //        filter.frameId = 0x444u;
        //        qDebug()<<filter.frameId;
        //        filter.frameIdMask = 0x0u;
        //        filter.format = QCanBusDevice::Filter::MatchBaseFormat;
        //        filter.type = QCanBusFrame::DataFrame;
        //        filterList.append(filter);
        //        m_canDevice->setConfigurationParameter(QCanBusDevice::RawFilterKey, QVariant::fromValue(filterList));
        m_canDevice->setConfigurationParameter(QCanBusDevice::BitRateKey,QVariant(bitrate));
        connectflag= m_canDevice->connectDevice();
        qDebug()<<"connecflag"<<connectflag;
    }
 
    if(connectflag)
    {
        connect(m_canDevice, &QCanBusDevice::errorOccurred,
                this, &MainWindow::processErrors);
        connect(m_canDevice, &QCanBusDevice::framesReceived,
                this, &MainWindow::processReceivedFrames);
        ui->canBT->setEnabled(false);
 
        // writeFrame
        QTimer *mytimer= new QTimer() ;
        connect(mytimer,&QTimer::timeout,this,[=](){
            QCanBusFrame frame;
            frame.setFrameId(0x123); // 设置CAN ID
            QByteArray payload;
            payload.append(0x01); // 设置要发送的数据
            payload.append(0x02);
            payload.append(0x03);
            payload.append(0x04);
            payload.append(0x05);
            payload.append(0x06);
            payload.append(0x07);
            payload.append(0x08);
            frame.setFrameType(QCanBusFrame::DataFrame);
//            frame.setExtendedFrameFormat(false);
            frame.setExtendedFrameFormat(true);
            frame.setPayload(payload); // 设置帧数据
            m_canDevice->writeFrame(frame);
        });
        mytimer->start(1000);
 
    }
}

  

连线图 参考 https://zhuanlan.zhihu.com/p/420285500

 

自己封装的接口

canlib.h

复制代码
#ifndef CANLIB_H
#define CANLIB_H

#include <QCanBusDevice>
#include <QStringList>
#include <QTimer>

#include <QtCore>
#include <QMutex>

#include<windows.h>

//修改日志
//20211103-1050     将传统单线程接收修改为多线程+锁的方式,目前测试无问题 锁使用 QMutexLocker locker(&mutex); 这个利用构造析构来加锁解锁,更安全.其实此处如何使用,无所谓

class Q_DECL_EXPORT CANLib : public QThread
{
    Q_OBJECT
public:
    CANLib();
    void run();
    ~CANLib();

    QStringList getUSBCANList();//得到当前 USBCAN list
    int openUSBCAN(int DevIndex, int channelIndex, int baudRate);//设置波特率  默认数据8位,无流控 无校验 1位停止位
    void closeUSBCAN();//关闭串口
    int sendInfo(QStringList list,int interval = 5);//发送数据
    int sendInfo(QString info);
    int canStatus();//

signals:
    void sigReceivedInfo(QString tem);
    void sigCANStateInfo(QString tem);

private:

    void _my_msleepByCPU(double mSleepTime);//设置ms延时
    void _my_usleepByCPU(double uSleepTime);//设置微秒延时

    QCanBusDevice *m_canDevice=nullptr;

    int openedUSBCAN = -1;      //打开的设备编号
    int openedChannel = -1;     //已经打开的channel,在打开按钮处赋值
    int openedBaudRate = -1;    //记录当前使用的波特率,点击不同的波特率时候 需要关闭之前的通讯 0 125k 1 250k
    QCanBusFrame candata[1024];  //缓存,用于接受数据
    QCanBusFrame sendData[1024]; //缓存,用于发送数据
    QTimer *timerReadData;      //用于定时读取设备数据//建议40ms一次或者100ms一次
    int startFlag = 0;          //开启关闭标志,不使用terminal

    QMutex mutex;
};

#endif // CANLIB_H
复制代码

canlib.cpp

复制代码
#include "canlib.h"

#include <QTimer>
#include <QDebug>
#include <QMap>
#include <QDateTime>
#include <QTime>
#include <QList>
#include <QCanBus>
#include <QTimer>
#include <QCanBusFrame>
#define myDebugMsg(msg) qDebug()<<QString("[Debug]  Time:%0  File:%1  Line:%2  Function:%3  Msg:%4").arg(QTime::currentTime().toString("hh:mm:ss.zzz")).arg(__FILE__).arg(__LINE__).arg(__FUNCTION__).arg(msg);
#define myDebugNum(msg) qDebug()<<QString("[Debug]  Time:%0  File:%1  Line:%2  Function:%3  Msg:%4").arg(QTime::currentTime().toString("hh:mm:ss.zzz")).arg(__FILE__).arg(__LINE__).arg(__FUNCTION__).arg(QString::number(msg));
#define myDebugInfo(msg) qDebug()<<msg;
#define myDebug qDebug()<<QString("[Debug]  Time:%0  File:%1  Line:%2  Function:%3").arg(QTime::currentTime().toString("hh:mm:ss.zzz")).arg(__FILE__).arg(__LINE__).arg(__FUNCTION__);

#define opendebuginfosend 0
//#define opendebuginforecv 1


#include <QCoreApplication>
CANLib::CANLib() : QThread()
{
    startFlag=1;
    //初始化时,定义好变量//计划每毫秒读取一次缓存
    timerReadData = new QTimer(this);
    timerReadData->setTimerType(Qt::PreciseTimer);
    connect(timerReadData,&QTimer::timeout,this,[=]() mutable{
        //
    });
}

void CANLib::run()
{
    while (startFlag==1) {
        Sleep(1000);
        //_my_usleepByCPU(1000);//延时1ms
//        if(openedUSBCAN<0 || openedChannel<0)continue;
//        int recvnum = VCI_GetReceiveNum(VCI_USBCAN2,openedUSBCAN,openedChannel);
//        QString res = "";
//        int ret = 0;

//        if(recvnum>=1023)recvnum = 1023;
//        {
//            QMutexLocker locker(&mutex);
//            ret = VCI_Receive(VCI_USBCAN2,openedUSBCAN,openedChannel,candata,1023);
//        }
////        mutex.lock();
////        ret = VCI_Receive(VCI_USBCAN2,openedUSBCAN,openedChannel,candata,1023);
////        mutex.unlock();
//        if(ret != 0xffffffff){
//            //遍历数据,并调用显示数据显示结果
//            for(int i=0;i<ret;i++){
//                //emit ...
//                res = "00000000"+QString::number(candata[i].ID,16);
//                if(candata[i].ExternFlag==0){
//                    res = res.right(3)+":";
//                }
//                else{
//                    res = res.right(8)+":";
//                }


//                for(int j=0;j<candata[i].DataLen;j++){
//                    int a = candata[i].Data[j];
//                    res += QString("00"+QString::number(a,16)).right(2);
//                }
//#ifdef opendebuginforecv
//                myDebugMsg(res.toUpper());
//#endif
//                emit sigReceivedInfo(res.toUpper());
//            }
//        }

    }
}

CANLib::~CANLib()
{
    closeUSBCAN();
    timerReadData->deleteLater();
}

QStringList CANLib::getUSBCANList()
{
    QStringList list;
//    int devNum = VCI_ScanDevice(1);
//    for(int i=0;i<devNum;i++){ list.append(QString("USBCAN %1").arg(i));}
    list.append(QString("USBCAN0"));
    return list;
}
int CANLib::canStatus()
{
    if(m_canDevice==nullptr){return -1;}
    if(m_canDevice->state()!=QCanBusDevice::CanBusDeviceState::ConnectedState){return -1;}
    return 1;
}

int CANLib::openUSBCAN(int DevIndex, int channelIndex, int baudRate)
{
    // const QString plugin="virtualcan";
    // qDebug()<< QCanBus::instance()->plugins();
    const QString plugin="peakcan";
    const int bitrate=baudRate*1000;
    bool connectflag=false;
    QString errorString;
    // QList<QCanBusDeviceInfo> m_interfaces;
    QList<QCanBusDeviceInfo> m_interfaces = QCanBus::instance()->availableDevices(plugin);
    if(!m_interfaces.empty()){
        qDebug()<<m_interfaces.begin()->name();
        m_canDevice=QCanBus::instance()->createDevice(plugin, m_interfaces.begin()->name(), &errorString);
    }
    else{
        qDebug()<<"do not find available interface for pcan";
        return -1;
    }

    if (!m_canDevice)
    {
        qDebug() <<"createDevice error" <<errorString;
        return -2;
    }
    else
    {
        /***peakcan do not support configuration key RawFilterKey***/
        //        QCanBusDevice::Filter filter;
        //        QList<QCanBusDevice::Filter> filterList;
        //        // filter all CAN bus packages with id 0x444 (base) or 0xXXXXX444 (extended)
        //        filter.frameId = 0x444u;
        //        qDebug()<<filter.frameId;
        //        filter.frameIdMask = 0x0u;
        //        filter.format = QCanBusDevice::Filter::MatchBaseFormat;
        //        filter.type = QCanBusFrame::DataFrame;
        //        filterList.append(filter);
        //        m_canDevice->setConfigurationParameter(QCanBusDevice::RawFilterKey, QVariant::fromValue(filterList));
        m_canDevice->setConfigurationParameter(QCanBusDevice::BitRateKey,QVariant(bitrate));
        connectflag= m_canDevice->connectDevice();
        qDebug()<<"connecflag"<<connectflag;
    }
    if(connectflag){
        connect(m_canDevice, &QCanBusDevice::errorOccurred,this, [=](QCanBusDevice::CanBusError error) mutable{
            switch (error) {
//            case QCanBusDevice::ReadError:
//            case QCanBusDevice::WriteError:
            case QCanBusDevice::ConnectionError:
            case QCanBusDevice::ConfigurationError:
            case QCanBusDevice::UnknownError:
//            case QCanBusDevice::OperationError:
//            case QCanBusDevice::TimeoutError:
                // qDebug()<<m_canDevice->errorString();
                // emit sigCANStateInfo("closed");
                closeUSBCAN();
                break;
            default:
                break;
            }
        });
        connect(m_canDevice, &QCanBusDevice::framesReceived,this, [=]() mutable{
            if (!m_canDevice){return;}

            while (m_canDevice->framesAvailable()){
                QCanBusFrame frame = m_canDevice->readFrame();
                //qDebug()<<frame.error();
                //qDebug()<<frame.frameId();//frame id,it's decimal
                //qDebug()<<frame.frameType();//1 means dataframe
                //qDebug()<<m_canDevice->state();

                QString view;
                if (frame.frameType() == QCanBusFrame::ErrorFrame){
                    view = m_canDevice->interpretErrorFrame(frame);
                }
                else if(frame.frameType()==QCanBusFrame::DataFrame){
                    view=frame.toString();
                    QString hexString="";
                    if(frame.hasExtendedFrameFormat()){
                        hexString = QString::number(frame.frameId(), 16).toUpper().rightJustified(8, '0');
                    }
                    else{
                        hexString = QString::number(frame.frameId(), 16).toUpper().rightJustified(3, '0');
                    }
                    hexString+=":";
                    hexString+=frame.payload().toHex().toUpper();
                    emit sigReceivedInfo(hexString);
                    // for (int j=0;j<Message[i].LEN;j++) {
                    //     hexString+=QString::number(Message[i].DATA[j], 16).toUpper().rightJustified(2, '0');
                    // }
                }
                //qDebug()<<view;
            }
        });
        // this->start();
        return 1;
    }
    return -3;

}

void CANLib::closeUSBCAN()
{
//    startFlag = 0;
//    //timerReadData->stop();
//    if(openedChannel>=0)VCI_ResetCAN(VCI_USBCAN2,openedUSBCAN,openedChannel);
//    else{ return; }
//    VCI_CloseDevice(VCI_USBCAN2,openedUSBCAN);
//    openedChannel = -1;
//    openedUSBCAN = -1;
//    openedBaudRate = -1;
    if(m_canDevice!=nullptr){
        m_canDevice->disconnectDevice();
        delete m_canDevice;
        m_canDevice=nullptr;
        emit sigCANStateInfo("closed");
    }
}

int CANLib::sendInfo(QStringList list, int interval)
{
    if(openedChannel<0)return -1;
    int len = list.size();
    int all=0;
    for(int i=0;i<len;i++){
        int res=sendInfo(list.at(i));
        if(res==1){all+=1;}
        if(interval>0){
            QCoreApplication::processEvents(QEventLoop::AllEvents);
            Sleep(interval);
        }
    }
    return all;



//    if(interval>0){
//        for(int i=0;i<len;i++){
//            sendInfo(list.at(i));
//            QCoreApplication::processEvents(QEventLoop::AllEvents);
//            Sleep(interval);
//        }
//    }
//    else{
//        for(int i=0;i<len;i++){
//            QStringList li = list.at(i).split(":");
//            sendData[i].ID = li[0].toUInt(Q_NULLPTR,16);
//            sendData[i].SendType = 0;
//            sendData[i].RemoteFlag = 0;
//            sendData[i].ExternFlag = 0;
//            for(int i=0;i<li[1].length()/2;i++){
//                sendData[i].Data[i] = li[1].mid(2*i,2).toUInt(Q_NULLPTR,16);
//            }
//            sendData[i].DataLen = li[1].length()/2;
//        }
//        int sendCount = 0;
//        {
//            QMutexLocker locker(&mutex);
//            sendCount = VCI_Transmit(VCI_USBCAN2,openedUSBCAN,openedChannel,sendData,len);
//        }
////        mutex.lock();
////        sendCount = VCI_Transmit(VCI_USBCAN2,openedUSBCAN,openedChannel,sendData,len);
////        mutex.unlock();
//        if(sendCount!=len){ return -1;}
//        else{return 1;}
//    }
//    return 1;
}

int CANLib::sendInfo(QString info)
{

#ifdef opendebuginfosend
    myDebugMsg(info);
#endif
    //if(openedChannel<0)return -1;
    //数据格式 001:3132333435363738
    if(info.contains(":")==false){return -1;}
    if(m_canDevice==nullptr){return -1;}
    if(m_canDevice->state()!=QCanBusDevice::CanBusDeviceState::ConnectedState){return -1;}
    QStringList li = info.split(":");
    QCanBusFrame frame;
    frame.setFrameId(li[0].toUInt(nullptr,16));
    if(frame.frameId()>0x7ff||li[0].length()>3){frame.setExtendedFrameFormat(true);}
    else{frame.setExtendedFrameFormat(false);}
    QByteArray arr;
    for(int i=0;i<li[1].length()/2;i++){
        arr.append(li[1].mid(2*i,2).toUInt(nullptr,16));
    }
    frame.setPayload(arr);
    //qDebug() <<"frame send:" <<frame.toString();
    //qDebug() <<"m_canDevice->busStatus():" <<m_canDevice->busStatus();
    //qDebug() <<"m_canDevice->state():" <<m_canDevice->state();
    return m_canDevice->writeFrame(frame);

}

// 精确延时毫秒
void CANLib::_my_msleepByCPU(double mSleepTime)
{
    LARGE_INTEGER litmp;
    LONGLONG Qpart1,Qpart2;
    double dfMinus = 0,dfFreq = 0,dfTime = 0;//不初始化是一个不好的习惯,而且会有bug

    //获得CPU计时器的时钟频率
    QueryPerformanceFrequency(&litmp);//取得高精度运行计数器的频率f,单位是每秒多少次(n/s),
    dfFreq = (double)litmp.QuadPart;

    QueryPerformanceCounter(&litmp);//取得高精度运行计数器的数值
    Qpart1 = litmp.QuadPart; //开始计时

    while((mSleepTime-dfTime*1000.000)>0.0000001){
        QueryPerformanceCounter(&litmp);//取得高精度运行计数器的数值
        Qpart2 = litmp.QuadPart; //终止计时

        dfMinus = (double)(Qpart2 - Qpart1);//计算计数器值
        dfTime = dfMinus / dfFreq;//获得对应时间,单位为秒,可以乘1000000精确到微秒级(us)
//        qDebug()<<"ms"<<QString::number(dfTime*1000.00,'f',9);
    }
}

void CANLib::_my_usleepByCPU(double uSleepTime)
{
    LARGE_INTEGER litmp;
    LONGLONG Qpart1,Qpart2;
    double dfMinus = 0,dfFreq = 0,dfTime = 0;//不初始化是一个不好的习惯,而且会有bug

    //获得CPU计时器的时钟频率
    QueryPerformanceFrequency(&litmp);//取得高精度运行计数器的频率f,单位是每秒多少次(n/s),
    dfFreq = (double)litmp.QuadPart;

    QueryPerformanceCounter(&litmp);//取得高精度运行计数器的数值
    Qpart1 = litmp.QuadPart; //开始计时

    while((uSleepTime-dfTime*1000000.000)>0.0000001){
        QueryPerformanceCounter(&litmp);//取得高精度运行计数器的数值
        Qpart2 = litmp.QuadPart; //终止计时

        dfMinus = (double)(Qpart2 - Qpart1);//计算计数器值
        dfTime = dfMinus / dfFreq;//获得对应时间,单位为秒,可以乘1000000精确到微秒级(us)
//        qDebug()<<"us"<<QString::number(dfTime*1000000.00,'f',9);
    }
}
复制代码

 

 

使用

复制代码
    // can
    toolCANLib = new CANLib();
    connect(toolCANLib, &CANLib::sigReceivedInfo,this,&MainWindow::receivedInfoAll);
    connect(toolCANLib, &CANLib::sigCANStateInfo,this,[=](QString cmd){
        if(cmd=="closed"){
            ui->btn_conn_close->setEnabled(false);
            ui->btn_conn_open->setEnabled(true);
            update_set_state("通讯关闭",-1);
        }
    });

    // 按钮打开关闭
    connect(ui->btn_conn_open, &QPushButton::clicked,this,[=](){
        ui->stackedWidget->setEnabled(false);
        toolCANLib->closeUSBCAN();
        QCoreApplication::processEvents(QEventLoop::AllEvents);
        str_data_version="";//软件版本清空,打开通讯就重读

        int baudRate=0;
        if(ui->data_conn_baud->currentText().toUpper().contains("125K")){baudRate = 125;}
        else if(ui->data_conn_baud->currentText().toUpper().contains("250K")){baudRate = 250;}
        else if(ui->data_conn_baud->currentText().toUpper().contains("500K")){baudRate = 500;}
        else if(ui->data_conn_baud->currentText().toUpper().contains("800K")){baudRate = 800;}
        else if(ui->data_conn_baud->currentText().toUpper().contains("1M")){baudRate = 1000;}
        else{ui->stackedWidget->setEnabled(true);return ;}

        int res = toolCANLib->openUSBCAN(0,0,baudRate);
        if(res<0){
            toolCANLib->closeUSBCAN();
        }
        else {
            ui->btn_conn_open->setEnabled(false);
            ui->btn_conn_close->setEnabled(true);
            ui->btn_conn_open->setStyleSheet("");
            ui->btn_conn_close->setStyleSheet("background-color: green;");
            update_set_state("通讯打开成功");
        }
        ui->stackedWidget->setEnabled(true);
    });
    connect(ui->btn_conn_close, &QPushButton::clicked,this,[=](){
         ui->btn_conn_close->setEnabled(false);
         ui->btn_conn_open->setEnabled(true);
         ui->btn_conn_close->setStyleSheet("");
         ui->btn_conn_open->setStyleSheet("background-color: green;");
         update_set_state("通讯关闭",-1);
        toolCANLib->closeUSBCAN();
    });
    ui->btn_conn_close->click();
复制代码

 

posted @   小城熊儿  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2021-11-22 qt 使用CRUD方式操作excel
点击右上角即可分享
微信分享提示