Qt 使用自带peakcan插件读取CAN FD数据

    项目上需要上位机和底层板子进行can fd通讯,上位机采集板子的数据并检测其工作情况,底层板子数据通过can fd进行传输。前提条件是安装了PeakOemDrv.exe这个驱动(供应商提供,网上应该也能下载到),然后上位机通过USB线连接板子硬件,硬件连接成功后,在设备管理器中可以查看设备信息,如下:

编写的peakcan接口主要参考了这篇文章:QT5使用PCAN读取CAN数据_qcanbusdevice-优快云博客

1、环境:Qt5.15.2 +VS2019。

2、前提条件:.pro中需要添加QT  +=  serialbus serialport。安装了PeakOemDrv.exe驱动。

3、编写的PeakCAN的代码:

peakcan.h

#ifndef PEAKCAN_H
#define PEAKCAN_H

#include <QCanBus>
#include <QObject>
#include <QTimer>

class PeakCAN : public QObject
{
    Q_OBJECT
public:
    PeakCAN(QString deviceName = "", QObject *parent = nullptr);
    ~PeakCAN();

    bool Connect();
    void Disconnect();
    void writeFrame(const quint32 id, const QByteArray &frame);

private slots:
    void processErrors(QCanBusDevice::CanBusError);
    void onReceiveFrames();
    void onStateChangeHandle(QCanBusDevice::CanBusDeviceState state);
    bool initDevice();
    void detectPcan();

signals:
    void connectedDone();
    void disconnectedDone();
    void framesReadReady(const QVector<QCanBusFrame> &);

private:
    QCanBusDevice *                  m_canDevice = nullptr;
    QList<QCanBusDeviceInfo>         m_interfaces;
    QCanBusDevice::CanBusDeviceState m_connectState;
    bool                             m_connectFalg;
    bool                             m_connected = false;
    QString                          m_devcieName;

    QTimer *              m_PcanDetectTimer    = nullptr;    //检测插入定时器
    int                   m_PcanDetectInterval = 5000;
    QVector<QCanBusFrame> m_frames;
};

#endif    // PEAKCAN_H

peakcan.cpp 

4、使用说明: new PeakCAN后,调用Connect()接口连接,由于实际的板子有2路can,而目前只用到了channel 0,所以在Connect()接口中,只连接到了通道0,如果需要连接多路信号,可能需要new 多个PeakCan,并指定设备名。PeakCAN收到消息后,会通过framesReadReady信号发出。向设备发送can时,调用writeFrame接口。

#include "peakcan.h"
#include <QCanBus>
#include <QCanBusFrame>
#include <QDateTime>
#include <QDebug>
#include <QThread>

PeakCAN::PeakCAN(QString deviceName, QObject *parent) : QObject(parent), m_devcieName(deviceName)
{
    m_connectFalg = false;
    qRegisterMetaType<QCanBusDevice::CanBusDeviceState>("QCanBusDevice::CanBusDeviceState");
    qRegisterMetaType<QVector<QCanBusFrame>>("QVector<QCanBusFrame>");
    m_PcanDetectTimer = new QTimer(this);
    connect(m_PcanDetectTimer, &QTimer::timeout, this, &PeakCAN::detectPcan);
}

PeakCAN::~PeakCAN()
{
    Disconnect();
    qDebug() << "PeakCAN destructiong...";
}

bool PeakCAN::Connect()
{
    m_connectFalg = true;
    if (m_canDevice == nullptr)
    {
        initDevice();
    }

    if (m_canDevice == nullptr)
    {
        return false;
    }

    if (!m_canDevice->connectDevice())
    {
        qDebug() << "PEAKCan connect fail!";
        m_canDevice->disconnectDevice();
        return false;
    }
    return true;
}

void PeakCAN::Disconnect()
{
    m_connectFalg = false;
    if (m_canDevice)
    {
        disconnect(m_canDevice, &QCanBusDevice::errorOccurred, this, &PeakCAN::processErrors);
        disconnect(m_canDevice, &QCanBusDevice::framesReceived, this, &PeakCAN::onReceiveFrames);
        disconnect(m_canDevice, &QCanBusDevice::stateChanged, this, &PeakCAN::onStateChangeHandle);
        m_canDevice->disconnectDevice();
    }
    m_PcanDetectTimer->stop();
}

void PeakCAN::processErrors(QCanBusDevice::CanBusError error)
{
    switch (error)
    {
        case QCanBusDevice::ReadError:
        case QCanBusDevice::WriteError:
        case QCanBusDevice::ConnectionError:
            qDebug() << m_canDevice->errorString();
            m_canDevice->resetController();
            break;
        case QCanBusDevice::ConfigurationError:
        case QCanBusDevice::UnknownError:
            qDebug() << m_canDevice->errorString();
            // m_canDevice->resetController();
            break;
        default:
            break;
    }
}

void PeakCAN::writeFrame(const quint32 ID, const QByteArray &data)
{
    if (!m_connectFalg)
    {
        return;
    }

    QCanBusFrame frame;
    frame.setFrameType(QCanBusFrame::DataFrame);
    // frame.setExtendedFrameFormat(ID > 0x7FF ? true : false); /* 是否为扩展帧 */ setFrameId时内部会自行设置扩展标志
    frame.setTimeStamp(QDateTime::currentMSecsSinceEpoch());    //时间戳
    if (data.size() > 8)
    {
        frame.setBitrateSwitch(true);    // BRS 位
        // frame.setFlexibleDataRateFormat(true);//FDF 位
    }
    frame.setFrameId(ID);
    frame.setPayload(data);
    if (m_canDevice)
    {
        m_canDevice->writeFrame(frame);
    }
}

bool PeakCAN::initDevice()
{
    if (!QCanBus::instance()->plugins().contains(QStringLiteral("peakcan")))
    {
        qDebug("peakcan plugin not available");
        return false;
    }

    const QString plugin = "peakcan";
    m_interfaces         = QCanBus::instance()->availableDevices(plugin);
    if (m_interfaces.empty())
    {
        qDebug() << "PEAKCan do not find available interface for pcan";
        m_PcanDetectTimer->start(m_PcanDetectInterval);
        return false;
    }

    m_PcanDetectTimer->stop();
    foreach (QCanBusDeviceInfo deviceInfo, m_interfaces)
    {
        if (deviceInfo.channel() == 0)    //只连接通道0
        {
            QString errorString;
            if (m_devcieName.isEmpty())
            {
                m_canDevice = QCanBus::instance()->createDevice(plugin, deviceInfo.name(), &errorString);
            }
            else if (deviceInfo.name() == m_devcieName)
            {
                m_canDevice = QCanBus::instance()->createDevice(plugin, deviceInfo.name(), &errorString);
                if (!m_canDevice)
                {
                    qDebug() << "PEAKCan createDevice error" << errorString;
                    qDebug() << "PEAKCan deviceName:" << deviceInfo.name() << " description:" << deviceInfo.description()
                             << " channel:" << deviceInfo.channel();
                }
                break;
            }
        }
    }

    if (!m_canDevice)
    {
        return false;
    }
    const int bitrate  = 500000;
    const int datarate = 2000000;
    m_canDevice->setConfigurationParameter(QCanBusDevice::CanFdKey, QVariant(true));              // canFD设置为true
    m_canDevice->setConfigurationParameter(QCanBusDevice::BitRateKey, QVariant(bitrate));         //波特率
    m_canDevice->setConfigurationParameter(QCanBusDevice::DataBitRateKey, QVariant(datarate));    //传输速率

    connect(m_canDevice, &QCanBusDevice::errorOccurred, this, &PeakCAN::processErrors);
    connect(m_canDevice, &QCanBusDevice::framesReceived, this, &PeakCAN::onReceiveFrames);
    connect(m_canDevice, &QCanBusDevice::stateChanged, this, &PeakCAN::onStateChangeHandle);
    return true;
}

void PeakCAN::detectPcan()
{
    initDevice();
    if (m_connectFalg && m_canDevice)
    {
        m_canDevice->connectDevice();
    }
}

//收到can消息处理
void PeakCAN::onReceiveFrames()
{
    if (m_canDevice)
    {
        m_canDevice->readAllFrames().swap(m_frames);
        emit framesReadReady(m_frames);
    }
}

void PeakCAN::onStateChangeHandle(QCanBusDevice::CanBusDeviceState state)
{
    m_connectState = state;
    if (state == QCanBusDevice::UnconnectedState)
    {
        emit disconnectedDone();
        m_connected = false;
    }
    else if (state == QCanBusDevice::ConnectedState)
    {
        m_connected = true;
        emit connectedDone();
    }
}

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值