基于DBC Signal Group生成Autosar SR接口(1)

文章目录

    • 前言
    • 实现方法
      • 结构体在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)开头,然后是数据的NameDataType,此处我们没有考虑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也提供了载体。

你可能感兴趣的:(Autosar笔记,DBC,Signal,Group)