用QT写CAN分析软件4---DBC文件读取

今天进行DBC文件的读取,ui界面如下

 

1、先新建singal类

.h

#ifndef DBCSINGALBASE_H
#define DBCSINGALBASE_H

#include <QObject>

class dbcsingalbase
{
public:
    dbcsingalbase();

    QString Name;   //名称
    int Start;      //启始位
    int Number;     //位长度
    int End;        // 结束位
    double Rate;    //分辩率
    double Offset;  //偏移
    QString Unit;   //单位
    QString Note;   //备注
    double MaxValue;    //最小值
    double MinValue;    //最大值
    double Value;       //实际值
    QString StrValue;   //显示值
    bool isSigned;        //有符号
    bool isMoto;        //是否摩托罗拉格式
    bool isEnum;      //

    quint8 multiplexer_type;    //see 'multiplexer type' above
    quint8 val_type;            //0:integer, 1:float, 2:double
    quint32 multiplexer_value;

    void GetMaxMinValue();

};

#endif // DBCSINGALBASE_H

2、新建message类

.h

#ifndef DBCMESSAGEBASE_H
#define DBCMESSAGEBASE_H

#include <QObject>
#include <QList>
#include "dbcsingalbase.h"
#include "candatabase.h"

class DbcMessageBase
{

public:
    DbcMessageBase();

    QList<dbcsingalbase> SingalList;

    QString Name;

    bool IsSend;

    quint32 SendCycle;

    QString SendNodeName;

    CanDataBase Can;

    bool isMoto;

    void SetMoto(bool moto);

};

#endif // DBCMESSAGEBASE_H

3、新建个处理DBC的类

.h

#ifndef DBCANALYSISMODEL_H
#define DBCANALYSISMODEL_H

#include <QObject>
#include <QList>
#include "dbcmessagebase.h"
#include "IDBCManager.h"

class DbcAnalysisModel : public QObject
{
    Q_OBJECT

private:
    DBCHandle m_hDBC;

public:
    explicit DbcAnalysisModel(QObject *parent = 0);
    ~DbcAnalysisModel();

    QString Name;
    quint32 BaudRate;
    qint16 Address;

    QList<DbcMessageBase> MsgList;

    bool GetList(QString filename);

signals:

public slots:
};

#endif // DBCANALYSISMODEL_H

4、编写DBC读取函数

bool DbcAnalysisModel::GetList(QString filename)
{
    QFile file(filename);

    file.open(QIODevice::ReadOnly|QIODevice::Text);

    MsgList.clear();

    while(!file.atEnd())
    {
        QByteArray line = file.readLine();
        QString str1 = QTextCodec::codecForName("GBK")->toUnicode(line);

       // qDebug()<< str1;
        
        if (str1.mid(0, 4) == "BO_ ")
        {
            QStringList strs1 = str1.trimmed().split(" ");
            DbcMessageBase fdb;

            fdb.Can.Id = strs1[1].toULong() & 0x1FFFFFFF;
            if (fdb.Can.Id > 0x7FF)
                fdb.Can.IsExtendFrame = true;

            fdb.Name = strs1[2].mid(0, strs1[2].length() - 1);
            //fdb.SendCycle = 0;

            if (strs1[strs1.length() - 1] != "Vector__XXX")
            {
                fdb.SendNodeName = strs1[strs1.length() - 1];
            }

            this->MsgList.append(fdb);
        }
         else if (str1.mid(0, 5) == " SG_ ")
        {
            dbcsingalbase dtb ;

            int index1 = str1.indexOf("SG_");
            int index2 = str1.indexOf(":");

            QString name = str1.mid(index1 + 3, index2 - index1 - 3).trimmed();
            dtb.Name = name;

            QStringList strs1 = str1.mid(index2 + 1, str1.length() - index2 - 1).split(" ");

            int i1 = strs1[1].indexOf('|');
            int i2 = strs1[1].indexOf('@');
            int start = (strs1[1].mid(0, i1).toInt());
            int number = (strs1[1].mid(i1 + 1, i2 - i1 - 1).toInt());
            int format = (strs1[1].mid(i2 + 1, 1).toInt());
            QString vtype = strs1[1].mid(i2 + 2, 1);

            if (vtype == "-")
                dtb.isSigned = true;

            dtb.Number = number;
            if (format == 1)
            {
                dtb.Start = start;
                dtb.isMoto = false;
            }
            else
            {
                int offset = 0;
                int end = 0;
                for (int j = 0; j < number; j++)
                {
                    end = start - j;
                    if ((end % 8 == 0) && (j != number - 1))
                        offset += 16;
                    end += offset;
                }

                dtb.Start = end;
                dtb.isMoto = true;
            }

            dtb.GetEnd();

            MsgList.back().SetMoto( dtb.isMoto);

            QStringList strs2 = strs1[2].replace("(", "").replace(")", "").split(",");
            dtb.Rate = strs2[0].toDouble();
            dtb.Offset = strs2[1].toDouble();

            QStringList strs3 = strs1[3].replace("[", "").replace("]", "").split("|");
            dtb.MinValue = (strs3[0].toDouble());
            dtb.MaxValue = (strs3[1].toDouble());

            if (dtb.MinValue == 0 && dtb.MinValue == dtb.MaxValue)
            {
                dtb.GetMaxMinValue();
            }

            dtb.Unit = strs1[4].replace("\"", "");

            MsgList.back().SingalList.append(dtb);
        }
    }
}

5、打开DBC按钮处理

void MainWindow::on_btnOpenDbc_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
                                                    "./",
                                                    tr("DBC文件 (*.dbc)"));
    ui->lbFilename->setText( fileName);

    if(this->Dbc->GetList(fileName))
    {
        ui->tbMsg->setColumnCount(5);
        ui->tbMsg->setRowCount(Dbc->MsgList.size());

        for(int i = 0;i<Dbc->MsgList.size();i++)
        {
            DbcMessageBase mb = Dbc->MsgList.at(i);
            QTableWidgetItem *tbi1 = new QTableWidgetItem(mb.Name);

            ui->tbMsg->setItem(i,0,tbi1);

            QTableWidgetItem *tbi2 = new QTableWidgetItem(QString::number(mb.Can.Id,16));

            ui->tbMsg->setItem(i,1,tbi2);

            QTableWidgetItem *tbi3 = new QTableWidgetItem(mb.isMoto?"Motorola":"Intel");

            ui->tbMsg->setItem(i,2,tbi3);

            QTableWidgetItem *tbi5 = new QTableWidgetItem(QString::number(mb.SendCycle));

            ui->tbMsg->setItem(i,3,tbi5);

            QTableWidgetItem *tbi6 = new QTableWidgetItem(mb.SendNodeName);

            ui->tbMsg->setItem(i,4,tbi6);

        }
    }
}

6、点南message表格显示对应的singal

void MainWindow::on_tbMsg_currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn)
{
    static int row = -1;

    if(currentRow != row)
    {
        row = currentRow;

         DbcMessageBase mb = Dbc->MsgList.at(row);

         ui->tbSingal->setColumnCount(10);
         ui->tbSingal->setRowCount(mb.SingalList.size());

         for(int i=0;i<mb.SingalList.size();i++)
         {
             dbcsingalbase sb = mb.SingalList.at(i);

             QTableWidgetItem *tbi1 = new QTableWidgetItem(sb.Name);

             ui->tbSingal->setItem(i,0,tbi1);

             QTableWidgetItem *tbi2 = new QTableWidgetItem(sb.Note);

             ui->tbSingal->setItem(i,1,tbi2);

             QTableWidgetItem *tbi3 = new QTableWidgetItem(QString::number(sb.Start));

             ui->tbSingal->setItem(i,2,tbi3);

             QTableWidgetItem *tbi4 = new QTableWidgetItem(QString::number(sb.Number));

             ui->tbSingal->setItem(i,3,tbi4);

             QTableWidgetItem *tbi5 = new QTableWidgetItem(QString::number(sb.End));

             ui->tbSingal->setItem(i,4,tbi5);

             QTableWidgetItem *tbi6 = new QTableWidgetItem(sb.isEnum?"枚举":"整形");

             ui->tbSingal->setItem(i,5,tbi6);

             QTableWidgetItem *tbi7 = new QTableWidgetItem(QString::number(sb.Rate));

             ui->tbSingal->setItem(i,6,tbi7);

             QTableWidgetItem *tbi8 = new QTableWidgetItem(QString::number( sb.Offset));

             ui->tbSingal->setItem(i,7,tbi8);

             QTableWidgetItem *tbi9 = new QTableWidgetItem(sb.Unit);

             ui->tbSingal->setItem(i,8,tbi9);

             QTableWidgetItem *tbi10 = new QTableWidgetItem(QString::number(sb.Value));

             ui->tbSingal->setItem(i,9,tbi10);
         }
    }
}

读取DBC文件完成

 

  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是基于QT C++的CAN DBC文件解析代码示例: 1. 首先需要引入相关头文件 ```C++ #include <QFile> #include <QTextStream> #include <QDebug> #include <QRegExp> ``` 2. 定义CAN信号结构体 ```C++ struct CanSignal { QString name; //信号名称 int startBit; //信号起始位 int bitLength; //信号长度 double factor; //信号因子 double offset; //信号偏移量 double minValue;//最小值 double maxValue;//最大值 QString unit; //信号单位 }; ``` 3. 定义CAN消息结构体 ```C++ struct CanMessage { int id; //消息ID QString name; //消息名称 QList<CanSignal> signals;//信号列表 }; ``` 4. 解析DBC文件 ```C++ void parseDBCFile(const QString& filePath, QList<CanMessage>& messages) { QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "open DBC file failed."; return; } QTextStream in(&file); QRegExp messageRegExp("^BO_\\s+(\\d+)\\s+(\\w+):\\s+(\\d+)\\s+(\\w+)"); QRegExp signalRegExp("^ SG_\\s+(\\w+)\\s+:\\s+(\\d+)\\|(\\d+)@([+-]?\\d+\\.?\\d*[eE]?[+-]?\\d*)\\s+\\(([+-]?\\d+\\.?\\d*[eE]?[+-]?\\d*)\\s*,\\s*([+-]?\\d+\\.?\\d*[eE]?[+-]?\\d*)\\)\\s+\\[(\\w+)\\]"); CanMessage message; while (!in.atEnd()) { QString line = in.readLine().simplified(); if (line.startsWith("BO_")) { if (message.id > 0) { messages.append(message); } message.signals.clear(); messageRegExp.indexIn(line); message.id = messageRegExp.cap(1).toInt(); message.name = messageRegExp.cap(2); } else if (line.startsWith(" SG_")) { signalRegExp.indexIn(line); CanSignal signal; signal.name = signalRegExp.cap(1); signal.startBit = signalRegExp.cap(2).toInt(); signal.bitLength = signalRegExp.cap(3).toInt(); signal.factor = signalRegExp.cap(4).toDouble(); signal.offset = signalRegExp.cap(5).toDouble(); signal.minValue = signalRegExp.cap(6).toDouble(); signal.maxValue = signalRegExp.cap(7).toDouble(); signal.unit = signalRegExp.cap(8); message.signals.append(signal); } } if (message.id > 0) { messages.append(message); } } ``` 5. 使用示例 ```C++ QList<CanMessage> messages; parseDBCFile("test.dbc", messages); foreach (const CanMessage& message, messages) { qDebug() << "Message ID:" << message.id << "Name:" << message.name; foreach (const CanSignal& signal, message.signals) { qDebug() << "Signal Name:" << signal.name << "Start Bit:" << signal.startBit << "Bit Length:" << signal.bitLength << "Factor:" << signal.factor << "Offset:" << signal.offset << "Min Value:" << signal.minValue << "Max Value:" << signal.maxValue << "Unit:" << signal.unit; } } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值