基于C#的整车CAN通讯DBC文件编程

最近需要实现基于Excel的发动机台架自动化测量系统,需要用到dbc通讯文件,特著此文,给需要的人
程序运行效果图

首先要定义存放DBC数据的结构体:首先是 信号类和报文类 定义。
此定义需遵循变量从属关系(一个DBC文件内有多个BO_,一个BO_下有多个SG_)
可以参考此文章,https://www.vecll.com/news/10.html,作者提供的思路比较清晰,本文所述代码基于此思路进行详细开发

//信号类
    public class Typedef_SG
    {
        public string Name;
        public int StartBit;
        public int Length;
        public int CodeType; //0=motorola,1=intel
        public string DataType; //-表示有符号型
        public double Factor;
        public double Offset;
        public double MinValue;
        public double MaxValue;
        public string Unit;
    }
    //报文类
    public class Typedef_BO
    {
        public uint ID;
        public string Name;
        public uint Length;
        public List<Typedef_SG> SG = new List<Typedef_SG>();
    }

全局变量声明与定义

	private bool IsEdited = false;
	public static Dictionary<string, string> dictDBC = new Dictionary<string, string>(); //根据信号名称反查,方便后续使用<SG.Name,BO.ID+BO[]+SG[]>
	List<Typedef_BO> BO_List = new List<Typedef_BO>(); //将报文类构建成一个报文列表
	Typedef_BO BO;

接下来定义了打开DBC文件的函数,

private void LoadDBCFile()
        {
            dictDBC.Clear();
            BO_List.Clear();
            DialogResult dialogResult = OpenDBCFile.ShowDialog();
            if (dialogResult == DialogResult.OK)
            {
                string DBCFilePath = OpenDBCFile.FileName;
                BottomLabel1.Text = DBCFilePath;
                Stopwatch sw = new Stopwatch();
                sw.Restart();                                                                //按行读取
                using (var reader = new StreamReader(DBCFilePath))
                {
                    int i = 0;
                    int SG_index = 0;
                    int BO_index = 0;                                                        //
                    string str_Line = "";
                    while ((str_Line = reader.ReadLine()) != null)                           //带数据行
                    {
                        i++;
                        Regex regexSG = new Regex(@"^ SG_ [.]*");                            //SG
                        Regex regexBO = new Regex(@"^BO_ \d+");                              //BO
                        try
                        {
                            if (regexSG.IsMatch(str_Line))                                       //SG length=9
                            {
                                //MessageBox.Show("in SG_ ,line="+i);
                                string[] SG_Line = str_Line.Split(' ');
                                if (SG_Line.Length != 9) throw new Exception("数据格式错误,Line=" + i);
                                Typedef_SG SG = new Typedef_SG();
                                SG.Name = SG_Line[2];                                            //Name
                                string[] SG4 = SG_Line[4].Split(new char[2] { '|', '@' });       //StartBit,Length,CodeType,DataType
                                SG.StartBit = Convert.ToInt16(SG4[0]);
                                SG.Length = Convert.ToInt16(SG4[1]);
                                SG.CodeType = Convert.ToInt16(SG4[2].Substring(0, 1));
                                SG.DataType = SG4[2].Substring(1, 1);
                                string[] SG5 = SG_Line[5].Split(new char[3] { '(', ',', ')' }); //Factor,Offset
                                SG.Factor = Convert.ToDouble(SG5[1]);
                                SG.Offset = Convert.ToDouble(SG5[2]);
                                string[] SG6 = SG_Line[6].Split(new char[3] { '[', '|', ']' }); //MinValue,MaxValue,Unit
                                SG.MinValue = Convert.ToDouble(SG6[1]);
                                SG.MaxValue = Convert.ToDouble(SG6[2]);
                                SG.Unit = SG_Line[7];                                           //Unit
                                BO.SG.Add(SG);                                                  //SG to List BO.SG
                                dictDBC.Add(SG.Name, BO.ID+ "," + (BO_index - 1) + "," + SG_index);                     //添加元素key,value同步加入字典,实现根据SG.Name反查出(BO.ID, BO[BO_index], SG[SG_index])
                                SG_index++;
                            }
                            if (regexBO.IsMatch(str_Line))                                      //BO length=5
                            {
                                BO = new Typedef_BO();                                          //BO实例化
                                SG_index = 0;
                                string[] BO_Line = str_Line.Split(' ');
                                if (BO_Line.Length != 5) throw new Exception("数据格式错误,Line=" + i);
                                BO.ID = Convert.ToUInt16(BO_Line[1]);
                                BO.Name = BO_Line[2];
                                BO.Length = Convert.ToUInt16(BO_Line[3]);
                                BO_List.Add(BO);
                                BO_index++;
                                //MessageBox.Show("in BO_ ,line=" + i+ " ,name=" + BO.Name);
                            }
                        }
                        catch (Exception ex)
                        { MessageBox.Show(ex.Message); }
                    }
                }
                sw.Stop();
            }
        }

根据信号名称查询dbc文件对应行BO_及SG_信息 函数定义如下

public static string dictDBCSearch(String SGname)
        {
            string Result = "";
            if (!dictDBC.ContainsKey(SGname))               //假如不存在元素
                Result = SGname + ",不存在";
            else
                Result = SGname + "的 BO[BO_index] ,SG[SG_index] = " + dictDBC[SGname];
            return Result;
        }

源码链接:https://download.csdn.net/download/qqwertccc/13764355
pudn已传

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
以下是基于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; } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值