使用Qt二次开发周立功CAN(三)

一、前言

在成功加载CAN接口函数库并打开CAN盒子的基础上,本文介绍如何在线程中完成报文的接收,报文格式的转化并通过TableWidget控件进行显示。编写过程参考了北京爱泰联合科技有限公司的DEMO http://www.itekon.com/download_2840.html

二、开辟子线程

因为是实时接受报文,比较占用资源,所以开辟一个线程,并在线程的run()函数中使用while循环来接收报文。
参考b站上面https://www.bilibili.com/video/BV1XW411x7NU?p=76线程开辟的方法,开辟一个子线程。

头文件如下:

#define MYTHREAD_H

#include <QThread>
#include"ControlCAN.h"

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = nullptr);
public:
    void ReceiveCanData();
    int closeFlag = 0;//接收数据

public:
    void ReceiveCloseFlag(int close_Flag);
signals:
    void ThreadSendCanData(QString strCANID,QString strFormat,QString strType,QString strLen,QString strData);//通过信号的方式,将子线程中的数据发送给主线程
    void CloseThreadFlag();//子线程发送关闭子线程信号
    void SendHydraulicSystemsInfo(float pressOfPowerReal,float pressOfPumpReal,float temperatureReal);
protected:
    void run();
public slots:
};

#endif // MYTHREAD_H

源文件如下:

#include "mythread.h"
#include<QDebug>
#include<QString>
#include<QByteArray>

MyThread::MyThread(QObject *parent) : QThread(parent)
{

}
void MyThread::run()
{
    ReceiveCanData();
}

三、接收数据

接收报文前需要定义报文接收的结构体VCI_CAN_OBJ frameinfo[1000];
通过VCI_Receive(设备编号,设备类型号(默认为0),CAN通道号,接收信息结构体,每一次接收个数,等待时间)函数接收数据。并通过QString定义的字符串,获得结构体中的ID,帧格式,帧类型,帧的数据长度(如果为数据帧),以及帧数据(如果为数据帧)。
源文件如下:

MyThread::MyThread(QObject *parent) : QThread(parent)
{

}
void MyThread::run()
{
    ReceiveCanData();
}
void MyThread::ReceiveCanData()

{
    
    VCI_CAN_OBJ frameinfo[1000];
    

    //接收
   // ULONG res = 0;

    //获取缓冲区中接收但尚未被读取的帧数.devtype=3:设备类型USBCAN1;devind=0:设备索引号;canind=0:CAN通道0
    //res = VCI_GetReceiveNum(20,0,0);
   // qDebug()<<"帧数"<<res;

    int len = 1;
    

    while(true)
    {
        if(closeFlag == 1)
            {
                emit CloseThreadFlag();
                break;
            }
        QString strCANID;
        QString strFormat;
        QString strType;
        QString strLen;
        QString strData;

        len = VCI_Receive(20,0,0,frameinfo,50,200);//VCI_Receive(设备编号(20为VCI_USBCAN_E_U),设备类型号(默认为0),CAN通道号,接收信息结构体,每一次接收个数,等待时间)函数接收数据。
    for(int i = 0; i < len; i++)
    {
        strCANID.clear();
        strFormat.clear();
        strData.clear();
        strLen.clear();
        strType.clear();

        strCANID = QString("0x");
        strCANID.append(QString::number(frameinfo[i].ID,16));
        qDebug()<<strCANID;
        //分析每一帧的格式,是数据帧还是远程帧,是标准帧还是扩展帧
        if(frameinfo[i].RemoteFlag == 0)
        {
            strFormat = "数据帧";
        }
        else
        {
            strFormat = "远程帧";
        }

        if(frameinfo[i].ExternFlag == 0)
        {
            strType = "标准帧";
        }
        else
        {
            strType = "扩展帧";
        }
        //如果是数据帧,获取数据帧里面的数据
        if(frameinfo[i].RemoteFlag == 0)
        {
            strLen = QString("%1").arg(frameinfo[i].DataLen);

            for(int j = 0; j < frameinfo[i].DataLen; j++)
            {
               // tmpstr = QString("%02 ").arg(frameinfo[i].DataLen);
                //QString tempStr = QString("%02").arg(frameinfo[i].Data[j]);
                strData.append(QString::number(frameinfo[i].Data[j],16));//以16进制的方式将数据放入strData字符串中
                //strData.append(tempStr);
                strData.append(" ");//数据之间添加空格
            }
        }
        emit ThreadSendCanData(strCANID,strFormat,strType,strLen,strData);
}

四、显示报文

通过相应按钮的槽函数开始子线程
程序如下:

thread0->start();

把子线程(thread0)发送的信号函数和主线程(this)中的槽函数连接(connect)
程序如下:

//连接线程发送数据信号和接受槽函数
    connect(thread0,&MyThread::ThreadSendCanData,this,&Widget::ReceiveThreadDataAndShow);

在主窗口的构造函数中初始化表格窗口(tableWidget)对象(tableWidget为ui界面中显示数据的表格)
程序如下:

    //为tablewidget设置格式
    ui->tableWidget->setColumnCount(6);//设置列数,不设置行数,行数动态增加
    //ui->tableWidget->setRowCount(1);
    ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"时间"<<"帧ID"<<"帧格式"<<"帧类型"<<"数据长度"<<"数据(HEX)");
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);//禁止修改表格中内容
   // ui->tableWidget->setShowGrid(false);
    ui->tableWidget->setColumnWidth(0,170);//设置第1列的宽度
    ui->tableWidget->setColumnWidth(2,70);//设置第3列的宽度
    ui->tableWidget->setColumnWidth(3,70);//设置第4列的宽度
    ui->tableWidget->setColumnWidth(4,70);//设置第5列的宽度
    ui->tableWidget->setColumnWidth(5,170);//设置第6列的宽度

接收报文并显示的槽函数,其中tableWidget为ui界面中显示数据的表格
程序如下:

//定义接受线程数据并显示的函数
void Widget::ReceiveThreadDataAndShow(QString strCANID, QString strFormat, QString strType, QString strLen, QString strData)
{

    //获得系统当前时间
    QDateTime time = QDateTime::currentDateTime();
    QString strTime = time.toString("yyyy-MM-dd hh:mm:ss.zzz");

    int rowCont;
    rowCont = ui->tableWidget->rowCount();//获取当前表格中行数
    ui->tableWidget->insertRow(rowCont);//在当前表格后插入一空行
    ui->tableWidget->setItem(rowCont,0,new QTableWidgetItem(strTime));//给表格添加时间戳

    ui->tableWidget->setItem(rowCont,1,new QTableWidgetItem(strCANID));//给表格添加ID
    ui->tableWidget->item(rowCont,1)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);//水平竖直居中

    ui->tableWidget->setItem(rowCont,2,new QTableWidgetItem(strFormat));//给表格添加帧格式(数据帧还是远程帧)
    ui->tableWidget->item(rowCont,2)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);//水平竖直居中

    ui->tableWidget->setItem(rowCont,3,new QTableWidgetItem(strType));//给表格添加帧类型
    ui->tableWidget->item(rowCont,3)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);//水平竖直居中

    ui->tableWidget->setItem(rowCont,4,new QTableWidgetItem(strLen));//给表格添加报文数据长度
    ui->tableWidget->item(rowCont,4)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);//水平竖直居中

    ui->tableWidget->setItem(rowCont,5,new QTableWidgetItem(strData));//给表格添加报文数据

    //ui->tableWidget->item(0,0)->setTextAlignment(Qt::AlignHCenter);

    ui->tableWidget->scrollToBottom();//滚动条处于最底部
    ui->tableWidget->show();
}

总结

这里对文章进行总结:
1.接收报文数据需要用到 VCI_Receive()接口函数
2.接收数据需要在子线程中进行
3.显示数据需要用到ui界面中的Table Widget控件
注意:接收函数需要用到信息的结构体;
子线程的开启需要在主线程中的控件来完成;
TableWidget采用动态增加行的方式。

LabVIEW是一种图形化程序语言,用于控制和测量系统的设计和自动化。CAN(Controller Area Network)是一种串行总线通信协议,常用于汽车和机械领域。LabVIEW的CAN模块提供了对CAN总线的支持,使用户能够使用LabVIEW进行CAN通信。 LabVIEW的CAN模块提供了多种CAN协议的支持,包括CAN 2.0B和CAN FD。通过这些协议,LabVIEW可以与CAN设备进行通信,实现数据的收发和控制命令的发送。 LabVIEW立功CAN二次开发可以帮助用户在现有的LabVIEW CAN模块的基础上进行功能扩展和定制开发。用户可以根据自己的需求,利用LabVIEW的图形化编程环境,添加自定义的CAN功能模块,实现特定的通信需求。 例如,用户可以通过LabVIEW立功CAN二次开发,实现对CAN总线上数据的解析和处理。用户可以编写自定义的数据解析算法,对CAN总线上传输的原始数据进行解析和转换,使其变成可理解的格式并进行后续的处理。 此外,LabVIEW立功CAN二次开发还可以帮助用户实现CAN数据的存储和分析。用户可以编写LabVIEW程序,将CAN数据保存到数据库中,并通过分析和绘制图表的方式对数据进行可视化展示和分析。 总之,LabVIEW立功CAN二次开发可以帮助用户充分利用LabVIEW的强大功能和易用性,实现对CAN总线的更加灵活和定制化的开发和应用。通过这种方式,用户可以更好地满足自己的需求,并提高系统的可靠性和性能。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值