01--背景
在项目对接的过程中,有时候因为合作关系亦或是保密协议的缘故,在合作开发一款车型时,有时候主机厂或是供应商只愿意提供dbc文件而不提供CAN矩阵,那么我们在进行信号信息的获取时只能通过读取dbc文件,非常麻烦。本文目的是在dbc的繁多信息中,提取自己所需要的信息,汇集在表格内,相当于自己制作一个CAN矩阵,该功能的实现能够大大提高后续开发的工作效率,避免一些低级错误的发生。
02--思路
首先需要一个待测试的dbc,然后通过MATLAB的一个专用函数获取dbc内所有的信息以及属性,同时通过MATLAB创建一个表格,通过定义变量链接到获取到的dbc属性,然后把这些关联写入到表格中,最后需要调整表格的变现形式,使之稍微美观和便于进行查找。
03--脚本实现
1.先准备一个测试的dbc,并新建一个脚本文件
2.给dbc一个变量名并且把最后需要保存的Excel文件名也定义出来
clc;clear; %清除工作区与MATLAB命令行窗口内容
dbcName = 'TestDbc.dbc'; % 此处替换成自己的dbc文件名
excelFileName = 'SigMsg.xlsx'; % 此处替换成要保存的excel文件名
3.读取dbc内的信息与属性
disp('### Reading information from dbc file...'); %显示接下来的动作
dbcdata = canDatabase(dbcName); %读取dbc内的信息与属性
这里介绍下函数canDatabase,可以通过帮助功能了解该函数的信息,
最终该函数会输出属性信息、属性、报文信息、报文、dbc名字、节点信息、节点、路径、信号信息、用户资料
我们将这几行代码运行下,
运行之后我们发现,左下角的工作区出现了我们定义的变量,
双击dbcdata,我们发现dbc内的属性已经全部被拉出来了
可以看到我们关心的是有55个报文,双击点开报文信息,MessageInfo,可以看到有信号信息,那么我们可以通过结构体引用的形式把我们需要的信息提取出来
假设我们以第2个报文为例
其报文名字为BMS1,可以看到在信号Signals这列有3个元素,所以该报文内定义了3个信号
我们点开SignalInfo,可以看到信号的详细属性
假设现在我们所需要的信息如下:
报文名字、报文ID、信号名字、信号描述、信号备注这5个信息
定义这5个信息作为Excel表头的变量
tableHead = ["MessageName","ID","SignalName","ValueDescription","Comment"];
创建一个元细胞组,使我们需要的信息能够按我们的需求填进元细胞组中
MsgInfo = cell(1,1); % 将当前报文信息填充到数组 MsgInfo 中
如果数量较少,我们可以通过结构体引用把需要的信息填进细胞组中,但是一旦我们需要的信息比较多,比如需要dbc内的所有属性,如果使用这种手动方式效率将非常低下,在这里我们使用一个for循环直接进行遍历
for j = 1:length(dbcdata.MessageInfo(2).Signals) %遍历该报文中的信号总数
MsgInfo{j,1} = dbcdata.MessageInfo(2).Name;
MsgInfo{j,2} = dbcdata.MessageInfo(2).ID;
MsgInfo{j,3} = dbcdata.MessageInfo(2).SignalInfo(j).Name;
MsgInfo{j,4} = dbcdata.MessageInfo(2).SignalInfo(j).ValueTable;
MsgInfo{j,5} = dbcdata.MessageInfo(2).SignalInfo(j).Comment; %将上述3个信号的5个信息填入到元细胞组中
end
上述代码中:
MsgInfo{j,1}代表填进第j行第1列
MessageInfo(2)代表报文中的第2个报文即 ‘BMS1’
SignalInfo(j)代表信号内的第j行
4.创建一个表格,把元细胞组转化为表格数据并写入到Excel中,并直接开
tableData = cell2table(MsgInfo,"VariableNames",tableHead);
disp('### write data to excel file...');
writetable(tableData, excelFileName);
% 创建 Excel 应用程序对象
Excel = actxserver('Excel.Application');
% 打开 Excel 应用程序
Excel.Visible = 1;
Workbooks = Excel.Workbooks;
% 打开一个工作簿
filepath = [pwd, '\', excelFileName];
Workbook = Workbooks.Open(filepath);
把所有的写好的脚本运行一下
可以发现正常生成了Excel文件并自动进行了打开
打开后的内容如下图所示:
打开后发现一个bug,那就是列ValueDescription为空白,打开属性栏,发现里面确实没有值
如果没有值,我们希望他显示一个短横杠,如果有值,能够正常显示
现在我们重新找一个报文ValueDescription是有值的
可以看到第6个报文内很多信号都有2个值
同样的代码,只需要改下数字(注意需要把刚刚生成的Excel文档关闭并删除或放到其他路径,且清除工作区间即命令行内容)
打开的结果如下:
该列仍然没有任何内容,需要在代码中创建一个函数(函数需要放在m文件的最末尾),把该列下的内容提取进来
function valueDescrip = getSigValueDescrip(sigValDescripStruct)
valueDescrip = '';
if isempty(sigValDescripStruct)
valueDescrip = '-';
return;
end
for i = 1:length(sigValDescripStruct)
valueDescrip = [valueDescrip, num2str(sigValDescripStruct(i).Value), ': ', sigValDescripStruct(i).Text, '; '];
end
end
该函数的作用为:如果提取的描述信息中空白的话则用横杠表示,若有值,将把值显示出来
在对应的行中把函数进行引用
重新运行的效果:
同样的如果需要所有报文的信息,最后呈现的形式为CAN矩阵的形式,需要在上述的for循环外面再嵌套一层for循环来遍历不同的报文信号,也就是说类似于
dbcdata.MessageInfo(2).SignalInfo(j).Name; 将用
dbcdata.MessageInfo(i).SignalInfo(j).Name;来表示
即用如下的报文:
最终效果如下图:
该脚本放在附件
-→单个报文
-→全部报文
~欢迎下载!
参考【Reference】:dbc文件自动转成 excel 表格_哔哩哔哩_bilibili
作者:快乐的宇航boy