Simulink建模助手系列-进阶2【解析Bus总线信号层次结构】

Simulink建模助手系列-进阶2

  • 功能介绍
  • [1. 总线信号信息的获取](#1. 总线信号信息的获取)
  • [2. 信号层次结构的解析](#2. 信号层次结构的解析)
  • [3. 利用结构树展示结果](#3. 利用结构树展示结果)
  • [4. 完整的示例代码](#4. 完整的示例代码)
  • 系列文章
    • [- 基础篇:](#- 基础篇:)
    • [- 进阶篇:](#- 进阶篇:)

功能介绍

本文主要分享如何对Bus模块的总线信号层级进行解析,Simulink本身有个类似的功能,如图1所示。本文主要介绍如何通过代码的方式实现相似的功能,之所以需要实现该功能,主要是为了具备解析Bus模块总线信号的能力,为后续实现一些关联功能提供基础(如根据总线信号的解析结果自动创建相关的数据字典、统计某个子系统中用到了总线中的哪些信号等)。


图1 Simulink的信号层次结构查看功能

本文实现的效果如图2所示。除了可以通过信号线解析,还可以通过Bus Creator和Bus Selector解析。增加对总线的子信号和子总线数量的显示。

图2 本文实现的信号层次结构解析效果

下面主要介绍如何获取总线的信号信息,如何解析总线信号的层次结构,如何通过结构树的方式展示信号的层次结构。

1. 总线信号信息的获取

有两种方式可以获取总线的信号信息:一种是通过Bus Selector 的InputSignals属性,如图3所示。这种方式比较简单,但是只适用于Bus Selector模块,局限性较大。

图3 Bus Selector的InputSignals属性的值

另一种是通过端口句柄的SignalHierarchy属性,关于SignalHierarchy属性的结果和值的形式如图4(a)和图4(b)所示。该方法相对更复杂,但适用性广,本文主要介绍此方法。
图4(a) 关于SignalHierarchy的帮助说明


图4(b) 端口的SignalHierarchy属性的值

为了获取SignalHierarchy属性,需要获取相应的端口句柄,对于信号线,需要获取的是来源端口;对于Bus Creator,获取的是输出端口;对于Bus Selector,获取的是输入端口。以下是主要的代码。

matlab 复制代码
% 自定义函数:根据block的port获取信号层次信息
function sh = getSignalHierarchy(myblock) 
	% 获取选中元素的类型
    type = get_param(myblock,'Type');

    % 获取选中元素的句柄
    myblock_handle = get_param(myblock,'Handle');

    % 根据不同的元素类型,选择不同的端口获取方法
    switch type
        case {'block'} % 对于不同的模块类型,选择不同的端口获取方法
            blocktype = get_param(myblock,'BlockType');
            switch blocktype
                case {'BusCreator'}
                    port_h = get_param(myblock_handle,'PortHandles');
                    port_h = port_h.Outport;
                case {'BusSelector'}
                    port_h = get_param(myblock_handle,'PortHandles');
                    port_h = port_h.Inport;
                otherwise
                    return
            end
        case {'line'}
            port_h = get_param(myblock_handle,'SrcPortHandle');
        otherwise
            return
end

2. 信号层次结构的解析

SignalHierarchy属性获取的总线信号层次如图4(b)所示,总线的信号信息包含在Children里,里面是多维的struct结构,其中SignalName是子信号的名称,如果子信号是总线时,其Children非空,包含的是其子信号,结构与本层的信号结构一致,可以发现这是一个嵌套的数据结构。本文的解析主要是需要将其平展开,对子信号是单信号还是总线信号进行区分,得到总线类型信号的集合及其所包含的子信号信息,如图5所示。这么做的目的是为了后续生成数据字典做准备。

图5 信号层次结构解析后的结果

因为SignalHierarchy属性的值是嵌套的形式,为了解析,本文采用递归的方式,逐级对Children的内容进行解析和整理。主要代码如下:

matlab 复制代码
% 自定义函数:递归解析信号层次结构
function bus_set = parseSignalHierarchy(sh, sig_parent) 
    sig_children = sh.Children;
    
    bus_set = []; %bus集合
    sigs = []; %当前bus的子信号列表
    for i = 1:length(sig_children)
        l_sh = sig_children(i);
        l_name = l_sh.SignalName;
        l_children = l_sh.Children;

        % 构造数据
        l_sig_parent = sprintf('%s.%s',sig_parent,l_name);
        i_sig = struct();
        i_sig.sigName = l_name;
        i_sig.sigType = 'var';
        i_sig.sigPath = l_sig_parent;

        % 判断是否为bus
        if ~isempty(l_children) % 非空,是bus
            i_sig.sigType = 'bus';
            l_bus_set = parseSignalHierarchy(l_sh,l_sig_parent); % 递归
            bus_set = [bus_set;l_bus_set]; % 搜集总线集合
        end
        sigs = [sigs;i_sig]; %构造信号的集合
    end

    % 构造结果
    t_bus = struct();
    busNames = strsplit(sig_parent,'.');
    t_bus.busName = busNames{end};
    t_bus.busSigs = sigs;
    bus_set = [t_bus; bus_set];
end

3. 利用结构树展示结果

根据SignalHierarchy属性的值创建结构树展示信号层次结构同样采用递归的方式,效果如图2所示。主要代码如下:

matlab 复制代码
% 自定义函数:递归解析信号层次结构生成结构树
function [num_var, num_bus] = treeSignalHierarchy(sh, tree_node) 
    sig_children = sh.Children;
    
    num_var = 0; % 单信号个数
    num_bus = 0; % 子总线个数
    for i = 1:length(sig_children)
        l_sh = sig_children(i);
        l_name = l_sh.SignalName;
        l_children = l_sh.Children;

        % 增加节点
        l_tree_node = uitreenode(tree_node,'Text',l_name);

        % 判断是否为bus
        if ~isempty(l_children) % 非空,是bus: bus+1
            num_bus = num_bus+1;
            [l_num_var, l_num_bus] = treeSignalHierarchy(l_sh,l_tree_node); % 递归
            num_var = num_var+l_num_var;
            num_bus = num_bus+l_num_bus;
        else % 是var:num_var+1
            num_var = num_var+1;
        end
    end

    if num_var + num_bus>0
        tree_node.Text = sprintf( ...
            '%s (子信号:%d, 子总线:%d)',tree_node.Text,num_var,num_bus);
    end
end

最后,额外说明下,为了能够获取选中的信号线,使用find_system()函数时需要使'FindAll = on',代码如下所示。加上此设置后find_system返回的是句柄值。

matlab 复制代码
selectedLine_h = find_system(gcs, ...
    'FindAll', 'on', ...
    'SearchDepth', 1, ...
    'Type','line', ...
    'Selected', 'on');  

4. 完整的示例代码

以选中信号线为例。

matlab 复制代码
% 构造界面
h_fig = uifigure('Name','信号层次结构解析结果(示例)');
ly_main = uigridlayout(h_fig,'RowHeight',{'1x'},'ColumnWidth',{'1x'});
tree_sigs = uitree(ly_main);

% 选中信号线
myblocks = find_system(gcs, ...
    'FindAll', 'on', ...
    'SearchDepth', 1, ...
    'Type','line', ...
    'Selected', 'on');
bus_sets = {};
for i = 1:length(myblocks)
    myblock = myblocks(i);

    % 获取信号信息
    sh = getSignalHierarchy(myblock);

    % 解析信号,返回总线类信号集合
    bus_set = parseSignalHierarchy(sh, '0');
    bus_sets{end+1,1} = bus_set;

    % 解析信号,生成结构树
    parent = uitreenode(tree_sigs,'Text',sprintf('%d: ###',i));
    treeSignalHierarchy(sh, parent);
end
% 全部展开
expand(tree_sigs,'all');

PS:可将这部分代码进一步封装成回调函数,集成到主界面里。

实现后的效果如下:

信号层次结构解析与显示

系列文章

- 基础篇:

Simulink建模助手系列-1【批量创建Goto和From】
Simulink建模助手系列-2【自动创建缺失的Goto】
Simulink建模助手系列-3【批量创建Inport和Outport】
Simulink建模助手系列-4【批量添加信号线】
Simulink建模助手系列-5【批量对齐模块】
Simulink建模助手系列-6【自动调整子系统高度和信号线】

- 进阶篇:

Simulink建模助手系列-进阶1【界面化并集成到Simulink的右键菜单】

相关推荐
@陈小鱼4 小时前
基于 Savitzky-Golay滤波器的超声图像运动分析方法
python·计算机视觉·matlab·信号处理
guygg881 天前
基于人工神经网络的彩色图像恢复 MATLAB实现
开发语言·计算机视觉·matlab
dracula0001 天前
Simulink建模助手系列-进阶1【界面化并集成到Simulink的右键菜单】
matlab
Evand J2 天前
matlab GUI制作界面的一些笔记(入门)
开发语言·笔记·matlab
dracula0002 天前
Simulink建模助手系列-6【自动调整子系统高度和信号线】
matlab
dracula0003 天前
Simulink建模助手系列-4【批量添加信号线】
matlab
dracula0003 天前
Simulink建模助手系列-5【批量对齐模块】
matlab
dracula0004 天前
Simulink建模助手系列-2【自动创建缺失的Goto】
matlab
Evand J4 天前
【UWB与IMU紧耦合定位,MATLAB例程】UWB的TOA定位方法,与IMU紧耦合,对目标轨迹定位并输出误差统计。适用于二维平面的高精度定位导航
开发语言·matlab·平面·uwb·组合导航