文章目录
- 前言
- 实现方法
- 结构体在Simulink中的定义
- SignalGroup提取
- 总结
前言
在开发Autosar CAN通信模块时,对于Signal Group需要建立对应的Interface,其中的数据类型实际是一个结构体,包含Group中的Signal的数据类型定义。手动建立比较费时间,本文介绍利用Matlab脚本自动生成SignalGroup对应的Interface
实现方法
主要方法通过正则表达式提取DBC中的SignalGroup,生成BUS类型的m脚本,再通过Matlab脚本建立Simulnk模型及端口,建立RTE Port及mapping最后编译生成Arxml。
结构体在Simulink中的定义
在生成BUS之前,首先得清楚BUS的m文件定义
手动建立一个Simulink Bus的数据类型,如下所示:
导出m文件,如下所示:
Bus = Simulink.Bus;
Bus.Description = '';
Bus.DataScope = 'Auto';
Bus.HeaderFile = '';
Bus.Alignment = -1;
Bus.PreserveElementDimensions = false;
saveVarsTmp{1} = Simulink.BusElement;
saveVarsTmp{1}.Name = 'a';
saveVarsTmp{1}.Complexity = 'real';
saveVarsTmp{1}.Dimensions = 1;
saveVarsTmp{1}.DataType = 'single';
saveVarsTmp{1}.Min = [];
saveVarsTmp{1}.Max = [];
saveVarsTmp{1}.DimensionsMode = 'Fixed';
saveVarsTmp{1}.SamplingMode = 'Sample based';
saveVarsTmp{1}.DocUnits = '';
saveVarsTmp{1}.Description = '';
saveVarsTmp{1}(2, 1) = Simulink.BusElement;
saveVarsTmp{1}(2, 1).Name = 'a1';
saveVarsTmp{1}(2, 1).Complexity = 'real';
saveVarsTmp{1}(2, 1).Dimensions = 1;
saveVarsTmp{1}(2, 1).DataType = 'uint8';
saveVarsTmp{1}(2, 1).Min = [];
saveVarsTmp{1}(2, 1).Max = [];
saveVarsTmp{1}(2, 1).DimensionsMode = 'Fixed';
saveVarsTmp{1}(2, 1).SamplingMode = 'Sample based';
saveVarsTmp{1}(2, 1).DocUnits = '';
saveVarsTmp{1}(2, 1).Description = '';
saveVarsTmp{1}(3, 1) = Simulink.BusElement;
saveVarsTmp{1}(3, 1).Name = 'a2';
saveVarsTmp{1}(3, 1).Complexity = 'real';
saveVarsTmp{1}(3, 1).Dimensions = 1;
saveVarsTmp{1}(3, 1).DataType = 'single';
saveVarsTmp{1}(3, 1).Min = [];
saveVarsTmp{1}(3, 1).Max = [];
saveVarsTmp{1}(3, 1).DimensionsMode = 'Fixed';
saveVarsTmp{1}(3, 1).SamplingMode = 'Sample based';
saveVarsTmp{1}(3, 1).DocUnits = '';
saveVarsTmp{1}(3, 1).Description = '';
Bus.Elements = saveVarsTmp{1};
clear saveVarsTmp;
上面的BUS定义了三个数据,对于需要生成的M文件,主要关注的是数据的排列序号,第二和第三个数据定义以saveVarsTmp{1}(x, 1)开头,然后是数据的Name及DataType,此处我们没有考虑Dimensions为多维(DBC中都是一维)
此处需要留意的是HeaderFile这个属性,在后面会着重提
SignalGroup提取
Matlab有解析DBC的API函数,但可惜的是,不能解析出SignalGroup,只能解析出Message和其中的Signal。不过,利用正则表达式,提取SiganlGroup也不是难事~
记事本打开DBC,查找Group,可以找到SignalGroup的定义,如下所示:
SIG_GROUP_ 258 TestGroupName 1 : TestGroupSignal1 TestGroupSignal2 TestGroupSignal3 TestGroupSignal4;
上面的定义中,数字表示的是Group所在的message id,后面跟的是Group的名称,再后面跟的是1(目前遇到的都是1,没有查过具体的定义,估计是和信号组复用相关的),再后面跟的就是Signal,最后以分号结尾。
正则表达式提取文本中的SignalGroup信息,m脚本如下:
fid = fopen(dbcfile_name,'r');
file_code = {''};
ct = 1;
while ~feof(fid)
file_code(ct,1)={fgets(fid)};
ct=ct+1;
end
can_signal_group_pattern1 = '(?<=SIG_GROUP_ ).+';%提取信号组信息
can_signal_group = regexp(file_code,can_signal_group_pattern1,'match');%取信号组信息
can_signal_group(cellfun(@isempty,can_signal_group))=[];%去除空字符串所在行
for i = 1:length(can_signal_group)
can_signal_group_name{i} = regexp(can_signal_group{i},'\S+','match');
end
此处can_signal_group_name包含Group中的元素,按空格分开,例如第一个为ID,第二个为GroupName,第三个为1,第四个为":",后面跟的是Signal
GroupStruct = struct('GroupName',{}, 'ID',{} ,...
'SignalName',{},'DataType',{});
for i = 1:length(can_signal_group_name)
can_signal_group_Struct(i).GroupName = can_signal_group_name{i}{1}{2};
can_signal_group_Struct(i).ID = can_signal_group_name{i}{1}{1};
can_signal_group_pattern_fen = '.+(?=;)';%用来去除最后一个分号
can_signal_group_name{i}{1}{length(can_signal_group_name{i}{1})} = regexp(can_signal_group_name{i}{1}{length(can_signal_group_name{i}{1})},can_signal_group_pattern_fen,'match');
can_signal_group_name{i}{1}{length(can_signal_group_name{i}{1})} = can_signal_group_name{i}{1}{length(can_signal_group_name{i}{1})}{1};
for j = 5:length(can_signal_group_name{i}{1})
can_signal_group_Struct(i).SignalName{j-4} = can_signal_group_name{i}{1}{j};
end
end
此处我们已经提取出了SignalGroup中的GroupName,ID,及其中的SignalName。其中还有一个关键信息,就是Signal的数据类型。此处我们利用Matlab自带的函数提取Signal的信息
db = canDatabase(dbcfile_name);
for i = 1:length(can_signal_group_Struct)
for j = 1:length(can_signal_group_Struct(i).SignalName)
for a = 1:length(db.MessageInfo)
for b = 1:length(db.MessageInfo(a).SignalInfo)
if(strncmp(can_signal_group_Struct(i).SignalName{j},db.MessageInfo(a).SignalInfo(b).Name,32))
can_signal_group_Struct(i).DataType{j} = db.MessageInfo(a).SignalInfo(b).Class;
a=1;
b=1;
break;
end
if(i == length(can_signal_group_Struct) )
break;
end
end
if(i == length(can_signal_group_Struct) )
break;
end
end
if(i == length(can_signal_group_Struct) )
break;
end
end
if(i == length(can_signal_group_Struct) )
break;
end
end
判断Messag的SignalName和Group中的SignalName是否一致,此处只取前32个字节,因为太长会导致DBC报错,Group中的Name也不会全
到此,我们已经提取了生成BUS所需的主要信号。
接下来就是生成M文件,及后面的生成接口模型了,下一次再说吧。
关于HeaderFile,主要是在生成Autosar文件的时候,没有配置该属性的话,会报错找不到对应的Type
总结
本文介绍了DBC中Signal Group的提取,在没接触Autosar软件时,没有用过SignalGroup,Signal成组之后,一方面可以更好的管理,另一方面,为E2E也提供了载体。