在有特殊需要时(通过DBC–模型)实现建模高效化,这个时候就需要我们将需求的DBC文件中的信号写成模型的输入出信号,在建模过程中会出现大量的复制工作,当数量到达一定程度时候,就会造成时间上的浪费,且不一定保证数据的准确性,所以在这里找了个脚本,供大家参考:
% 将CAN矩阵DBC文件转换为excel文件
% 用途:
% 将CAN矩阵(Database)DBC文件转换为excel文件,便于查找报文中的信号
% 用canDatabase()读入DBC文件,xlswrite()写入excel文件
% 读入DBC文件名
[infile,path] = uigetfile({'*.dbc','CANdb Network'},'选择要转换的CAN Database文件');
if isequal(infile,0)
warndlg('没有选择任何文件,不会转换任何文件!','文件选取警告','modal');
else
DBCfile = [path,infile];
candb = canDatabase(DBCfile);
[messageRow, ~] = size(candb.MessageInfo);
% 获取DBC文件转换成xlsx表后的总行数(报文和信号的总行数),xlsx最大支持1048576行
signalRowCount = 0;
for messageIndex = 1:messageRow
[signalRow, ~] = size(candb.MessageInfo(messageIndex).SignalInfo);
signalRowCount = signalRowCount + signalRow;
end
msgTableRowMax = messageRow + signalRowCount;
xlsRowMax = 65536;
% 预留一行给表格标题(表格标题需要占用一行)
if msgTableRowMax > xlsRowMax-1
opts = struct('WindowStyle','modal','Interpreter','tex');
warmsg = ['\fontsize{10}转换后的表格长度超过',xlsRowMax,'行!',newline,...
'请注意选择保存的文件格式:',newline,...
'.xls文件最多支持65536行',newline,...
'.xlsx文件最多支持1048576行',newline...
'而.csv、.txt 或 .dat(带分隔符的文本文件)文件则没有限制'];
warndlg(warmsg,'文件长度警告',opts);
end
% candb文件转换成Table
messageTable = candbc2excel(candb);
% 创建报文结构体
% 因结构体增加行比表要方便故采用结构体数据结构
messageStruct = struct('MsgName',{}, 'ID_HEX',{},'DLC_Byte',{}, 'TxNode',{},'RxNodes',{},'CycleTime',{} ,'Tx_Method',{} ,'FrameFormat',{},'ProtocolMode',{},...
'SignalName',{}, 'ByteOrder',{}, 'StartBit',{}, 'BitLength',{},'Factor',{},'Class',{},'Offset',{},'Initial_Value',{},'Units',{}, 'ValueTable',{},...
'Minimum',{}, 'Maximum',{}, 'SignalComment',{},'SignalNumble',{},'ValueType',{},'ValueTableNumbles',{});
[messageRow, ~] = size(candb.MessageInfo);
tableIndex = 1; % 结构体行号
for messageIndex = 1:messageRow
messageStruct(tableIndex).MsgName = candb.MessageInfo(messageIndex).Name;
% messageStruct(tableIndex).ID_Decimal = candb.MessageInfo(messageIndex).ID;
messageStruct(tableIndex).ID_HEX = ['0x',dec2hex(candb.MessageInfo(messageIndex).ID)];
if candb.MessageInfo(messageIndex).Extended
messageStruct(tableIndex).FrameFormat = 'Extended';
else
messageStruct(tableIndex).FrameFormat = 'Standard';
end
messageStruct(tableIndex).ProtocolMode=candb.MessageInfo(messageIndex).ProtocolMode;
% if isequal(messageStruct(tableIndex).ProtocolMode{1},'J1939PG')==1 %如果是J1939P格式
% messageStruct(tableIndex).
% end
messageStruct(tableIndex).DLC_Byte = candb.MessageInfo(messageIndex).DLC;
% 将TxNodes的值(字符串元胞)合并到一行,便于填充到表格中
[TxNodesRow, TxNodesCol] = size(candb.MessageInfo(messageIndex).TxNodes);
TxNodes = '';
for TxNodesRowIndex = 1:TxNodesRow
for TxNodesColIndex = 1:TxNodesCol
TxNodes =[TxNodes, candb.MessageInfo(messageIndex).TxNodes{TxNodesRow,TxNodesCol}];
if (TxNodesRow>1 || TxNodesCol>1) && (TxNodesRowIndex < TxNodesRow || TxNodesColIndex < TxNodesCol)
TxNodes =[TxNodes,', '];
end
end
end
messageStruct(tableIndex).TxNode = TxNodes;
% 将RxNodes的值(字符串元胞)合并到一行,便于填充到表格中 % %这个里面应从每个message里去取RxNodes,而不是从每个signal里去取
[RxNodesRow, RxNodesCol] = size(candb.MessageInfo(messageIndex).SignalInfo(1).RxNodes);
RxNodes = '';
for RxNodesRowIndex = 1:RxNodesRow
for RxNodesColIndex = 1:RxNodesCol
RxNodes =[RxNodes, candb.MessageInfo(messageIndex).SignalInfo(1).RxNodes{RxNodesRowIndex,RxNodesColIndex}];
if (RxNodesRow>1 || RxNodesCol>1) && (RxNodesRowIndex < RxNodesRow || RxNodesColIndex < RxNodesCol)
RxNodes =[RxNodes,', '];
end
end
end
messageStruct(tableIndex).RxNodes = RxNodes;%%
MessageX=candb.MessageInfo(messageIndex).AttributeInfo;
MsgAttribuinfIndex=1;
for MsgAttribuinfIndex=1:size(MessageX,1)
if isequal('GenMsgSendType',MessageX(MsgAttribuinfIndex).Name)
messageStruct(tableIndex).Tx_Method=candb.MessageInfo(messageIndex).AttributeInfo(MsgAttribuinfIndex).Value;
end
if isequal('GenMsgCycleTime',MessageX(MsgAttribuinfIndex).Name)
messageStruct(tableIndex).CycleTime=candb.MessageInfo(messageIndex).AttributeInfo(MsgAttribuinfIndex).Value;
end
end
messageStruct(tableIndex).SignalNumble =length(candb.MessageInfo(messageIndex).Signals);
tableIndex = tableIndex + 1;
sigSize = size(candb.MessageInfo(messageIndex).SignalInfo);
for signalIndex = 1:sigSize
messageStruct(tableIndex).TxNode = TxNodes;
messageStruct(tableIndex).RxNodes = RxNodes;%%
messageStruct(tableIndex).SignalName = candb.MessageInfo(messageIndex).SignalInfo(signalIndex).Name;
messageStruct(tableIndex).SignalComment = candb.MessageInfo(messageIndex).SignalInfo(signalIndex).Comment;
messageStruct(tableIndex).StartBit = candb.MessageInfo(messageIndex).SignalInfo(signalIndex).StartBit;
messageStruct(tableIndex).BitLength = candb.MessageInfo(messageIndex).SignalInfo(signalIndex).SignalSize;
% 将valueTable的值(字符串元胞)合并到一行,便于填充到表格中
[valueTableRow, ~] = size(candb.MessageInfo(messageIndex).SignalInfo(signalIndex).ValueTable);
messageStruct(tableIndex).ValueTableNumbles = valueTableRow;%每一个signal都有VALUE table ,这里定义value tabel大小
valueTable = '';
for valueTableIndex = 1:valueTableRow
valueTable = [valueTable, candb.MessageInfo(messageIndex).SignalInfo(signalIndex).ValueTable(valueTableIndex).Text,'=',...
num2str(candb.MessageInfo(messageIndex).SignalInfo(signalIndex).ValueTable(valueTableIndex).Value)];
if (valueTableRow > 1) && (valueTableIndex < valueTableRow)
valueTable = [valueTable,', '];
end
end
messageStruct(tableIndex).ValueTable = valueTable;
if candb.MessageInfo(messageIndex).SignalInfo(signalIndex).Signed
messageStruct(tableIndex).ValueType = 'Signed';
else
messageStruct(tableIndex).ValueType = 'Unsigned';
end
messageStruct(tableIndex).Factor = candb.MessageInfo(messageIndex).SignalInfo(signalIndex).Factor;
messageStruct(tableIndex).Class = candb.MessageInfo(messageIndex).SignalInfo(signalIndex).Class;
messageStruct(tableIndex).Offset = candb.MessageInfo(messageIndex).SignalInfo(signalIndex).Offset;
messageStruct(tableIndex).Minimum = candb.MessageInfo(messageIndex).SignalInfo(signalIndex).Minimum;
messageStruct(tableIndex).Maximum = candb.MessageInfo(messageIndex).SignalInfo(signalIndex).Maximum;
messageStruct(tableIndex).Units = candb.MessageInfo(messageIndex).SignalInfo(signalIndex).Units;
% FIND the signal initial value
SignalsX=candb.MessageInfo(messageIndex).SignalInfo(signalIndex);
SignalsXIndex=1;
for SignalsXIndex=1:size(SignalsX.AttributeInfo,1)
if isequal('GenSigStartValue' ,SignalsX.AttributeInfo(SignalsXIndex).Name)
messageStruct(tableIndex).Initial_Value=candb.MessageInfo(messageIndex).SignalInfo(signalIndex).AttributeInfo(SignalsXIndex).Value;
end
end
if strcmpi((candb.MessageInfo(messageIndex).SignalInfo(signalIndex).ByteOrder),'BigEndian')
messageStruct(tableIndex).ByteOrder = 'Motorola';
elseif strcmpi((candb.MessageInfo(messageIndex).SignalInfo(signalIndex).ByteOrder),'LittleEndian')
messageStruct(tableIndex).ByteOrder = 'Intel';
else
messageStruct(tableIndex).ByteOrder = candb.MessageInfo(messageIndex).SignalInfo(signalIndex).ByteOrder;
end
tableIndex=tableIndex+1;
end
end
% 报文结构体转换成表
messageTable = struct2table(messageStruct);
end
% 写入xls文件
filter = {'*.xlsx','Excel 工作簿'; '*.xls','Excel 97-2003 工作簿'; '.xlsb','Excel 二进制工作簿';...
'*.csv; .txt; .dat','带分隔符的文本文件'};
filename = removeExt(infile);
% function filenameNonExt = removeExt(filename)
filenamelength = length(filename);
for index = filenamelength:-1:1
if filename(index) ~= '.'
filename(index) = '';
else
filename(index) = '';
break;
end
end
filenameNonExt = filename;
[outfile,path,indx] = uiputfile(filter,'选择保存文件',filename);
if isequal(outfile,0)
warndlg('没有输入要保存的文件,将不会保存任何文件!','文件保存警告','modal');
else
writetable(messageTable,[path,outfile]);
end
有疑问或错误的地方欢迎留言,我们共同探讨