用QT写CAN分析软件3--多线程接收数据

 

今天利用QT多线程来接收CAN的数据

1、首先新建一个candatabase的类来表示CAN到 的每一个帧数据

#ifndef CANDATABASE_H
#define CANDATABASE_H

#include <QObject>
#include <QDateTime>

class CanDataBase : public QObject
{
    Q_OBJECT
public:
    explicit CanDataBase(QObject *parent = 0);

    QDateTime Time;

    uint Id;

   unsigned char *Data;

    QString StrData;

    int Len;

    bool IsSend;

    bool IsExtendFrame;

    bool IsRemoteFrame;

    void SetTime(QDateTime time);

    void SetIsSend(bool send);

    void SetData(uint id,unsigned char * data,int len,bool extend = false,bool remote = false);

    void GetStringData();


signals:

public slots:
};

#endif // CANDATABASE_H
#include "candatabase.h"

CanDataBase::CanDataBase(QObject *parent) : QObject(parent)
{
    IsSend = false;
    IsExtendFrame = false;
    IsRemoteFrame = false;
}

void CanDataBase::SetTime(QDateTime time)
{
    this->Time = time;
}

void CanDataBase::SetIsSend(bool send)
{
    this->IsSend = send;

}

void CanDataBase::SetData(uint id,unsigned char * data,int len,bool extend,bool remote)
{
    this->Id = id;
    this->Data =data;
    this->IsExtendFrame = extend;
    this->IsRemoteFrame = remote;
    this->Len = len;
}

void CanDataBase::GetStringData()
{
    QString str ;

    for(int i=0;i<this->Len;i++)
    {
        str += QString("%1 ").arg( this->Data[i],2,16,QLatin1Char('0'));
    }

    this->StrData = str;

   // return str;
}

2、再新建个类,cansetmodel来处理收收的数据

void CanSetModel::DataReceive()
{
    ZCAN_Receive_Data can_data[100];
    ZCAN_ReceiveFD_Data canfd_data[100];
    UINT len;
    while(isStart)
    {
        if (len = ZCAN_GetReceiveNum(chHandle, TYPE_CAN))
        {
            len = ZCAN_Receive(chHandle, can_data, 100, 50);
            AddData(can_data, len);
        }
        if (len = ZCAN_GetReceiveNum(chHandle, TYPE_CANFD))
        {
            len = ZCAN_ReceiveFD(chHandle, canfd_data, 100, 50);
            AddData(canfd_data, len);
        }
    }
}

void CanSetModel::AddData(const ZCAN_Receive_Data *data, UINT len)
{
    QString item;
    for (UINT i = 0; i < len; ++i)
    {
        const ZCAN_Receive_Data& can = data[i];
        const canid_t& id = can.frame.can_id;

        CanDataBase *cdb = new CanDataBase();

        cdb->SetData(GET_ID(id),(unsigned char*)can.frame.data,can.frame.can_dlc,IS_EFF(id),IS_RTR(id));

        AddData(cdb);
    }
}

void CanSetModel::AddData(const ZCAN_ReceiveFD_Data *data, UINT len)
{
    QString item;
    for (UINT i = 0; i < len; ++i)
    {
        const ZCAN_ReceiveFD_Data& canfd = data[i];
        const canid_t& id = canfd.frame.can_id;

        CanDataBase *cdb = new CanDataBase();

        cdb->SetData(GET_ID(id),(unsigned char*)canfd.frame.data,canfd.frame.len,IS_EFF(id),IS_RTR(id));

        AddData(cdb);
    }
}

void CanSetModel::AddData(CanDataBase *cdb)
{
    cdb->SetTime(QDateTime::currentDateTime());
    cdb->GetStringData();
   // qDebug()<<"ID:" <<cdb->Id<<"数据:"<<cdb->StrData;

    emit this->DataUpdata(cdb);
}

3、在主程序.h文件中定义线程变量

  CanSetModel *CanSet;

  QThread *myThread;

signals:
     void StartDataReceive();

4、在主程序,c文件初始化函数的加入

 CanSet = new CanSetModel;

    myThread = new QThread(this);

    CanSet->moveToThread(myThread);

    connect(this,&MainWindow::StartDataReceive,CanSet,&CanSetModel::DataReceive);

    connect(this,&MainWindow::destroyed,this,&MainWindow::CloseWin);

    connect(CanSet,&CanSetModel::DataUpdata,this,&MainWindow::UpdataReceive);

5、在can的连接函数的加入启动线程的启动接收

 ui->btnConnect->setText("断开连接");

 myThread->start();
 emit this->StartDataReceive();

6、处理接收到的数据在界面上显示出来

void MainWindow::UpdataReceive(CanDataBase *cdb)
{
    QString  str;
    str += cdb->IsSend?"发送 ":"接收 ";
    // str += QString::number(cdb->sTime / 1000000.0,'f',6);
    str += cdb->Time.toString("HH:mm:ss.zzz");
    str += "  ID:0x";
    str += QString::number(cdb->Id,16);
    str += cdb->IsExtendFrame?" 扩展帧 ":" 标准帧 ";
    str += " 数据:";
    str += cdb->StrData;

    QListWidgetItem *item = new QListWidgetItem(str);

    if(cdb->IsSend)
        item->setForeground(Qt::red);

    ui->lwDataDisplay->addItem(item);
    ui->lwDataDisplay->scrollToBottom();

    if(  ui->lwDataDisplay->count() >= 50)
        ui->lwDataDisplay->removeItemWidget(  ui->lwDataDisplay->takeItem(0));
}

现在就可以完整的接收与发送CAN数据了

使用的是周立功USBCANFD_200U

下步进行DBC文件的读取与数据解析。

  • 7
    点赞
  • 90
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
Qt中,可以使用QThread类来实现多线程接收图像数据。以下是一个简单的例子: 1. 创建一个继承自QThread的类,如下所示: ``` class ImageReceiver : public QThread { Q_OBJECT public: explicit ImageReceiver(QObject *parent = nullptr); signals: void imageReceived(QImage image); protected: void run() override; private: // 定义接收图像数据的方法 }; ``` 2. 实现run()方法,在该方法中实现接收图像数据的逻辑。可以使用Qt的网络类(如QTcpSocket、QUdpSocket等)来接收数据,也可以使用第三方库(如OpenCV)来实现。 ``` void ImageReceiver::run() { // 接收图像数据的逻辑 // 例如使用QTcpSocket接收数据 QTcpSocket socket; socket.connectToHost("127.0.0.1", 8000); if (socket.waitForConnected()) { while (true) { // 读取数据 QByteArray data = socket.readAll(); // 将数据转换为QImage对象 QImage image = QImage::fromData(data); // 发送信号,通知主线程接收到了图像数据 emit imageReceived(image); } } } ``` 3. 在主线程中创建ImageReceiver对象,并连接信号和槽,如下所示: ``` ImageReceiver *receiver = new ImageReceiver(this); connect(receiver, &ImageReceiver::imageReceived, [=](QImage image) { // 在主线程中处理接收到的图像数据 // 例如显示图像 ui->label->setPixmap(QPixmap::fromImage(image)); }); receiver->start(); ``` 在上述代码中,我们在主线程中创建了一个ImageReceiver对象,并连接了imageReceived信号和一个Lambda表达式槽。当ImageReceiver对象接收到图像数据时,会发送imageReceived信号,主线程中的Lambda表达式槽会被触发,处理接收到的图像数据,并将其显示在界面上。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值