当用户编写了自定义的S函数或者使用Simulink标准库中的模块搭建子系统后,可以通过封装为其设计显示外观,追加参数对话框。
封装是构建一个以对话框为接口的交互界面的过程,它将复杂的模块逻辑关系隐藏起来,封装之后仅提供给用户GUI界面填写参数。用户仅需操作对话框即可实现自定义的功能。
11.1 Mask Editor封装模块
Mask Editor封装的对象有两种:
- Simulink Library中的模块构成的子系统,每个参数已经具有变量名和依附的控件,只需将其链接到新封装的GUI控件上即可;
- S函数编写的模块,需要为每个参数创建变量名和参数控件。
11.1.1 封装模块构成的子系统
y=ax^2+b;
右击Mask→Create Mask
包括4个页面:
- Icon&Ports:编辑子系统的模块外观,如在子系统图标中添加线条、文本和图像等;
- Parameters&Dialog:添加或修改模块参数,并为其设计控件类型;
- Initialization:编辑子模块的初始化脚本;
- Documentation:添加子模块的功能介绍及Help文档路径。
Icon&Ports
- disp('y=a*x^2+b');
将字符串显示在子系统框图的中央。
- text(x,y,'text'):x、y为坐标对,表示text相对于远点所显示的位置;
- text(x,y,'text','horizontalAlignment','halign','verticalAlignment','valign'):设置文本显示的坐标和方位;
- text(x,y,'text','texmode','on'):开启tex文本模式。
text(0,0,'y=a*x^2+b','horizontalAlignment','left','verticalAlignment','bottom');
通过Icon Units开启归一化,坐标范围0~1。
在text和disp函数语句之前使用color函数,可以规定文本显示时所使用的颜色,参数可为blue、green、red、cyan、magenta、yellow、black。
color('magenta'); text(0.3,0.3,'y=a*x^2+b','horizontalAlignment','left','verticalAlignment','bottom');
如果使用多种颜色,可以使用多个color分段调整文字的颜色。
- image:将图片展示到子系统或S函数模块框图上。
image(imread('Mask_demo01.jpg'));将
图片全伸展展示。
image(imread('Mask_demo01.jpg'),'top-left');
部分区域显示。
在定义完Parameters&Dialog之后,可以通过plot函数绘制图像到所封装的方框图上。
在Icon drawing commands中输入以下代码。
a=str2num(get_param(gcbh,'g_a')); b=str2num(get_param(gcbh,'g_b')); t=0:0.1:10; plot(t,a*t.^2+b);
Icon units选择AutoScale。
封装子系统的模块图标时,可以使用Port_label函数设置输入输出端口的显示名称
- port_label('port_type',port_number,'label','texmode','on');
port_type是指输入或输出端口,用input、output表示,当子系统为使能子系统、触发子系统或与流控制相连的Action子系统时,也可以指定Enable、trigger或Action端口。
port_number为port_type指定的端口类型存在多个端口时端口的序号,从1开始。
label为在指定端口显示的文本字样。
texmode表示tex模式开启与否。
在Icon drawing commands中输入以下代码。
port_label('input',1,'In','texmode','on'); port_label('output',1,'Out','texmode','on');
Parameters&Dialog
- Parameter:包括edit、popup、radiobutton和checkbox等控件,其具有value属性,用户可输入或选择参数的值,并将该值以变量的形式传递到模块内部使用,用户可以定义控件参数发生变化时所触发的回调函数。
- Display:作用是提示用户信息,比如文字或图片。
- Container:含Panel、tab、group box等,可以进行分组,控件tab和group box内部还可以再使用Mask Controls。其中tab控件与其他控件有所不同,不能直接添加到模块对象中,需要与称作tabcontainer的隐藏控件共同使用。这些控件仅仅在视觉上起到简明、美观的提示作用,没有value属性和回调函数。
- Action:包括超链接和按钮两种控件,可通过单击动作触发用户自定义的回调函数,但是控件本身没有变量名,也不必传递到封装的模型或S函数内部的功能。
Dialog Box是当前对话框已经包含的控件信息表格,表格默认显示3个属性:type、Prompt、Name,分别表示控件的类型、说明标签和变量名。
属性列表:
属性名 | 作用说明 |
Name | 控件变量名 |
Value | 控件变量的值 |
Prompt | 控件作用提示文字 |
Type | 控件类型选择 |
Evaluate | 控件中输入的内容作为字符串,进行一次eval(str)操作 |
Tunable | 仿真过程中控件值是否可变 |
Read only | 只读,不可编辑 |
Hidden | 隐藏控件 |
Never save | 即使控件改变也不保存 |
Enable | 仅在Read only时不使能,用户不能编辑控件,显示为灰色 |
Visible | 控制控件是否可见,仅当Hidden时使用 |
Callback | 编写或调用控件的回调函数 |
Item location | New/Current row,设定控件放在当前行或者另起一行 |
Prompt location | Top/Left,设定说明文字在控件的上方或左方 |
输入非法性检查(输入字母则报错):
function check_num(param) % This function check if the value of param is a number data type. val = get_param(gcbh, param); if isletter(val) errordlg(['Input value of ', param(end) ,' must be a number data-type!']); return; end
Initialization
主要用于定义模块的初始化命令,已经封装过的参数名将列在左侧。
此页面可以填入M代码。
模块的Initialization commands在以下时刻执行:
- 当Icon draw commands或Initialization commands里更改封装参数时;
- 当Icon draw commands有内容时,翻转或旋转模块;
- 双击打开模块的参数对话框或单击参数对话框上的Apply/OK/Cancel按钮关闭对话框时;
- 当使用set_param函数更改模块参数的值时,赋相同值也会触发;
- 拷贝此模块到同一模型中或其他模型中;
- 模型运行仿真时;
- 模型编译生成代码时;
- 模型工具栏中选择Updata diagram时。
如果需要在上述时刻触发某些动作,或者重新刷新模块的外观,可以在这里编写M脚本或调用M函数。
Documentation
用来补充模块的说明信息及Help按钮的功能。
Type的内容显示到模块参数对话框的左上角,Description的内容则紧随其后。
11.1.2 封装S函数编写的模块
直接按11.1.1中方法Mask即可。
11.2 编程自动封装模块
11.2.1模块的属性
>> get(gcbh) Path: 'mymodel' Name: 'y=a*x^2+b' Tag: '' Description: '' Type: 'block' Parent: 'mymodel' Handle: 5.0001 HiliteAncestors: 'none' RequirementInfo: '' FontName: 'auto' FontSize: -1 FontWeight: 'auto' FontAngle: 'auto' Selected: 'on' MaskType: 'Custom' MaskDescription: 'This block supplies a demo of masking.' MaskHelp: '' MaskPromptString: 'a|b' MaskStyleString: 'edit,edit' MaskVariables: 'g_a=@1;g_b=@2;' MaskTunableValueString: 'on,on' MaskCallbackString: 'check_num('g_a');|check_num('g_b');' MaskEnableString: 'on,on' MaskVisibilityString: 'on,on' MaskToolTipString: 'on,on' MaskVarAliasString: '' MaskInitialization: '' MaskSelfModifiable: 'off' MaskDisplay: 'a=str2num(get_param(gcbh,'g_a'));↵b=str2num(get_param(gcbh,'g_b'));↵t=0:0.1:10;↵plot(t,a*t.^2+b);' MaskBlockDVGIcon: '' MaskIconFrame: 'on' MaskIconOpaque: 'opaque' MaskIconRotate: 'none' MaskPortRotate: 'default' MaskIconUnits: 'autoscale' MaskValueString: '1|20' MaskRunInitForIconRedraw: 'off' MaskTabNameString: '' Mask: 'on' MaskCallbacks: {2×1 cell} MaskEnables: {2×1 cell} MaskNames: {2×1 cell} MaskPropertyNameString: 'g_a|g_b' MaskPrompts: {2×1 cell} MaskStyles: {2×1 cell} MaskTunableValues: {2×1 cell} MaskValues: {2×1 cell} MaskToolTipsDisplay: {2×1 cell} MaskVisibilities: {2×1 cell} MaskVarAliases: {2×1 cell} MaskWSVariables: [1×2 struct] MaskTabNames: {2×1 cell} MaskObject: [] Ports: [1×9 double] Position: [1×4 double] Orientation: 'right' PortRotationType: 'default' ForegroundColor: 'black' BackgroundColor: 'white' DropShadow: 'off' IOType: 'none' NamePlacement: 'normal' ShowName: 'on' HideAutomaticName: 'on' Priority: '' Commented: 'off' AttributesFormatString: '' TargetArchitectureMapping: {} InstantiateOnLoad: 'off' PolySpaceEndComment: '' PolySpaceStartComment: '' AncestorBlock: '' ReferenceBlock: '' SourceLibraryInfo: '' LibraryVersion: '' UserDataPersistent: 'off' UserData: [] CompiledIsActive: 'on' RTWdata: [] HDLData: [] Diagnostics: '' DialogParameters: [1×1 struct] IntrinsicDialogParameters: [1×1 struct] AlgorithmParameters: [1×1 struct] SecondaryAlgorithmParameters: [1×1 struct] CompiledSampleTime: [-1 0] InputSignalNames: {''} OutputSignalNames: {''} ModelParamTableInfo: [] StatePerturbationForJacobian: '1.0e-05' SCDEnableBlockLinearizationSpecification: 'off' SCDBlockLinearizationSpecification: [] CopyFcn: '' DeleteFcn: '' UndoDeleteFcn: '' LoadFcn: '' ModelCloseFcn: '' PreSaveFcn: '' PostSaveFcn: '' InitFcn: '' StartFcn: '' PauseFcn: '' ContinueFcn: '' StopFcn: '' NameChangeFcn: '' ClipboardFcn: '' DestroyFcn: '' PreCopyFcn: '' OpenFcn: '' CloseFcn: '' PreDeleteFcn: '' ParentCloseFcn: '' MoveFcn: '' BlockType: 'SubSystem' BlockDescription: 'Select the settings for the subsystem block. To enable parameters for code generation, select 'Treat as atomic unit'.' LinkStatus: 'none' StaticLinkStatus: 'none' PortConnectivity: [2×1 struct] PortHandles: [1×1 struct] LineHandles: [1×1 struct] CompiledPortWidths: [0×0 struct] CompiledPortDimensions: [0×0 struct] CompiledPortDataTypes: [0×0 struct] CompiledPortUnits: [0×0 struct] CompiledPortComplexSignals: [0×0 struct] CompiledPortFrameData: [0×0 struct] DataTypeOverride_Compiled: 'UseLocalSettings' MinMaxOverflowLogging_Compiled: 'UseLocalSettings' Capabilities: [1×1 Capabilities] IOSignalStrings: [] RuntimeObject: [0×1 double] ExtModeUploadOption: 'none' ExtModeLoggingSupported: 'off' ExtModeLoggingTrig: 'off' ShowPortLabels: 'FromPortIcon' BlockChoice: '' TemplateBlock: '' MemberBlocks: '' Permissions: 'ReadWrite' ErrorFcn: '' PermitHierarchicalResolution: 'All' TreatAsAtomicUnit: 'off' MinAlgLoopOccurrences: 'off' PropExecContextOutsideSubsystem: 'off' SystemSampleTime: '-1' RTWSystemCode: 'Auto' RTWFcnNameOpts: 'Auto' RTWFcnName: '' RTWFileNameOpts: 'Auto' RTWFileName: '' FunctionInterfaceSpec: 'void_void' FunctionWithSeparateData: 'off' RTWMemSecFuncInitTerm: 'Inherit from model' RTWMemSecFuncExecute: 'Inherit from model' RTWMemSecDataConstants: 'Inherit from model' RTWMemSecDataInternal: 'Inherit from model' RTWMemSecDataParameters: 'Inherit from model' IsSubsystemVirtual: 'on' Variant: 'off' VariantControl: '' OverrideUsingVariant: '' GeneratePreprocessorConditionals: 'off' AllowZeroVariantControls: 'off' PropagateVariantConditions: 'off' ActiveVariant: '' ActiveVariantBlock: '' TreatAsGroupedWhenPropagatingVariantConditions: 'on' Location: [1×4 double] Open: 'off' PortBlocksUseCompactNotation: 'off' ScrollbarOffset: [-106 -133] SetDomainSpec: 'off' DomainSpecType: 'Deduce' CompiledDomainSpecType: 'Unset' ModelBrowserVisibility: 'off' ModelBrowserWidth: 200 ScreenColor: 'white' CurrentBlock: 'Gain' CurrentOutputPort: [] Blocks: {6×1 cell} Lines: [5×1 struct] DeleteChildFcn: '' PaperOrientation: 'landscape' PaperPosition: [1×4 double] PaperPositionMode: 'auto' PaperType: 'usletter' PaperSize: [11 8.5000] PaperUnits: 'inches' TiledPaperMargins: [1×4 double] TiledPageScale: 1 ShowPageBoundaries: 'off' ZoomFactor: '100' ReportName: '' g_a: '1' g_b: '20'
inspect(gcbh)
与封装有关的属性列表:
属性名 | 属性的值 | 作用说明 |
MaskType | 'Custom' | Mask Editor的Documentation页面的参数 |
MaskDescription | 'This block supplies a demo of masking.' | Mask Editor的Documentation页面的参数 |
MaskHelp | 'helpview('xxx.html');' | Mask Editor的Documentation页面的参数 |
MaskPromptString | 'a|b' | 参数的说明字符串,不同参数说明字符之间使用'|'分隔 |
MaskStyleString | 'edit,edit' | 参数的控件类型字符串,两两之间使用','分隔 |
MaskVariables | 'g_a=@1;g_b=@2;' | 参数变量名及其编号的字符串,两两之间使用';'分隔 |
MaskTunableValueString | 'on,on' | 表征参数是否在仿真时间内可调,使用','分隔 |
MaskCallbackString | 'check_num('g_a');|check_num('g_b');' | 表示参数Callback调用的内容字符串,使用'|'分隔 |
MaskEnableString | 'on,on' | 表示参数是否使能的字符串,使用','分隔 |
MaskVisibilityString | 'on,on' | 表示参数是否可见的字符串,使用','分隔 |
MaskToolTipString | 'on.on' | 表示当鼠标停留在模块外观框图范围内是是否在提示框显示参数值 |
MaskInitialization | '' | Initialization Command的内容字符串 |
MaskDisplay | 'a=str2num(get_param(gcbh,'g_a')); |
Icon Draw Commands的内容字符串 |
MaskValueString | '1|20' | 模块封装参数的当前值,用'|'分隔 |
MaskCallbacks | Cell类型的MaskCallbackString | 可以使用元胞数组的下标进行访问或编辑 |
MaskEnables | Cell类型的MaskEnableString | 可以使用元胞数组的下标进行访问或编辑 |
MaskNames | Cell类型的参数名 |
可以使用元胞数组的下标进行访问或编辑 |
MaskPropertyNameString | g_a|g_b | 字符形式,将参数变量名用'|'分隔并连接起来 |
MaskPrompts | Cell类型的MaskPromptsString | 可以使用元胞数组的下标进行访问或编辑 |
MaskStyles | Cell类型的MaskStylesString | 可以使用元胞数组的下标进行访问或编辑 |
MaskTunableValues | Cell类型的MaskTunableValuesString | 可以使用元胞数组的下标进行访问或编辑 |
MaskValues | Cell类型的MaskValuesString | 可以使用元胞数组的下标进行访问或编辑 |
MaskToolTipsDisplay | Cell类型的MaskToolTipsString | 可以使用元胞数组的下标进行访问或编辑 |
MaskVisibilities | Cell类型的MaskVisibilitiesString | 可以使用元胞数组的下标进行访问或编辑 |
MaskTabNames | Cell型数组,每个元素为对应参数所在tab页面的名字 | 可以使用元胞数组的下标进行访问或编辑 |
帮助文档:https://www.mathworks.com/help/simulink/slref/mask-parameters.html
11.2.2 使用set_param和get_param封装模块
- ParameterValue=get_param(Object,ParameterName)
Object表示模块或者模型的句柄或模型模块路径,ParameterName表示模块或模型的属性。
- set_param(Object,ParameterName,value)
parameterName和value可以多组成对出现。
例:
set_param('mymodel/y=a*x^2+b','Maskvisibilities',{'on','off'})
使用Excel编辑封装:
function masktool(block, excelfile) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % This function help to mask parameters into block selected. % MaskNames should not be the same % MaskPrompts, MaskNames, MaskStyles, popupcontents, MaskTabs, MaskCallbackStrings % are written in Excel and this function can automatically transfer them % % block - the block need to be masked % excelfile - parameters saved in the excelfile % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % index definition promts_index = 1; names_index = 2; styles_index = 3; popups_index = 4; tabs_index = 5; callbacks_index = 6; % get data in excelfile [num, str] = xlsread(excelfile); % get mask prompts and saved as cell format promts = str(2:end,promts_index); % get mask names and saved as cell format names = str(2:end,names_index); % change names to MaskVariables format len = length(names); maskvar = ''; for ii = 1 : len maskvar = [maskvar, names{ii}, '=@', num2str(ii), ';']; %OK end % get mask styles and saved as cell format styles = str(2:end,styles_index); % get mask tab names tabname = str(2:end, tabs_index); % get callbacks strings callbackstr = str(2:end, callbacks_index); %get block's handle blockhandle = get_param(block,'Handle'); % get model properties prop = get(blockhandle); % mask promts into block set_param(blockhandle, 'MaskPrompts', promts); % mask names into block (MaskNames or MaskPropertyNameString is a readonly property) %set_param(blockhandle, 'MaskNames', names); set_param(blockhandle, 'MaskVariables', maskvar); % mask styles intoblock set_param(blockhandle, 'MaskStyles', styles); % check popup to write strings style = str(2:end, styles_index); % get popup strings popups = str(2:end, popups_index); % popuplen = length(popups); % for ii = 1 :popuplen % str2pro = popups{ii}; % str2pro(findstr(popups{ii} ,char(10))) = ''; %char(10) = line change token, delete it % popups{ii} = str2pro; % end % get MaskStyleString stylestring = get_param(blockhandle, 'MaskStyleString'); % get empty start index from MaskStyleString and its length and its total number emptystart = regexp(stylestring,'<empty>'); lenempty = length('<empty>'); if ~isempty(emptystart) numtorep = length(emptystart); % draw popup content from excelfile content = cell(numtorep); count = 1; num = length(style); for ii = 1:num if strcmp(style{ii}, 'popup')||strcmp(style{ii}, 'radiobutton') content{count} = str(ii + 1, popups_index); % content keep format as xxx|xxx|xxx count = count + 1; end end end % part stylestring to seperate parts % create cell using () not {} if ~isempty(emptystart) strpart = cell(numtorep + 1); strpart{1} = stylestring(1: emptystart(1) - 1); for ii = 2 : numtorep strpart{ii} = stylestring(emptystart(ii-1) + lenempty :emptystart(ii) - 1); end strpart{numtorep + 1} = stylestring(emptystart(end) + lenempty : end); % insert content into strpart maskstring =strpart{1}; for ii = 1: numtorep maskstring = strcat(maskstring, content{ii}); maskstring = strcat(maskstring, strpart{ii + 1}); end % cell changed to string stylestring = char(maskstring); % delete char(10) (which is not \n or \r) stylestring(findstr(stylestring, char(10))) = ''; %delete char(10) change line token % set MaskStyleString into block set_param(blockhandle, 'MaskStyleString', stylestring); end % set tab names set_param(blockhandle, 'MaskTabNames', tabname); % format callback str to xx|xx|xx|xx style but not display in callback dialog % cbnum = length(callbackstr); % cbstr = ''; % for ii = 1:cbnum % cbstr = [cbstr, callbackstr{ii},'|']; % end % cbstr % set MaskCallbacks set_param(blockhandle, 'MaskCallbacks', callbackstr); % get model name modelname = get_param(blockhandle, 'Name'); %modelpath = get_param(blockhandle, 'Path'); %fullname = fullfile(modelpath, modelname); % write Parameters automatically paramstr = get_param(blockhandle, 'MaskPropertyNameString'); paramstr(findstr(paramstr,'|')) = ','; set_param(blockhandle, 'Parameters', paramstr); % write S-Function name automatically set_param(blockhandle, 'FunctionName', excelfile); % print OK info disp([modelname, ' Mask Over!']);
>> masktool(gcbh,'BlkName.xls'); S-Function Mask Over!
11.2.3 使用Simulink.Mask类封装模块
Simulink.Mask类给模块创建一个封装对象,再通过对象的子方法来操作其各个属性。Simulink.Mask类提供的方法包括以下操作:
- 创建、拷贝、删除模块的封装;
- 创建、拷贝、删除模块封装的参数;
- 决定封装的对象模块;
- 获取封装时的工作空间变量。
>> maskObj=Simulink.Mask.get(gcbh) maskObj = Mask - 属性: Type: 'Custom' Description: 'This block supplies a demo of masking.' Help: '' Initialization: '' SelfModifiable: 'off' Display: 'a=str2num(get_param(gcbh,'g_a'));↵b=str2num(get_param(gcbh,'g_b'));↵t=0:0.1:10;↵plot(t,a*t.^2+b);' IconFrame: 'on' IconOpaque: 'opaque' RunInitForIconRedraw: 'off' IconRotate: 'none' PortRotate: 'default' IconUnits: 'autoscale' Parameters: [1×2 Simulink.MaskParameter] ParameterConstraints: [0×0 Simulink.Mask.Constraints] CrossParameterConstraints: [0×0 Simulink.Mask.CrossParameterConstraints] BaseMask: [0×0 Simulink.Mask]
MaskObj成员列表:
属性成员名 | 说明 |
Type | Mask Type |
Description | Mask Description |
Help | 打开help文档的代码 |
Initialization | 初始化命令 |
SelfModifiable | 是否使能模块修改自身内容,如popup的下拉菜单内容在Callback中被改变 |
Display | 绘制模块外观的代码 |
IconFrame | IconFrame是否可见 |
IconOpaque | 模块图标是否透明 |
RunInitForIconRedraw | 在执行模块外观绘制前是否必须执行初始化命令 |
IconRotate | 模块外观图标是否跟随模块一起旋转 |
IconUnits | 模块外观图标的单位设置,'pixel|autoscale|normalized' |
Parameters | 封装参数集合,类型为Simulink.MaskParameters |
BaseMask | 未使用属性 |
Simulink.Mask类子方法列表:
子方法名 | 功能说明 |
addParameter | 向模块中增加一个参数,参数名与值成对输入,当所封装模块与Simulink标准库有关联时,使用此函数会报错 |
copy | 将一个模块的封装拷贝到另外一个模块 |
create | 为未封装的模块创建一个封装对象 |
delete | 为模块解封装并删除封装对象变量 |
get | 获取模块的封装并存为一个对象变量 |
getDialogControl | 查找封装对象中的控件,参数为控件的变量名Name,返回被查找对象变量及其父对象变量 |
isMaskWithDialog | 当前对象是否封装了对话框 |
getOwner | 获取当前封装所依附的模块 |
getParameter | 获取某个参数的属性,输入参数为这个参数的Name |
getWorkspaceVariables | 获取当前封装所使用的所用参数并将参数名与值作为结构体变量返回 |
numParameters | 返回封装中参数的个数 |
removeAllParameters | 删除封装中所有的参数,一般不建议使用。当删除的Mask的Owner与Simulink标准库中存在链接关系的话,禁止删除 |
set | 设置封装某个属性的值,用法类似set_param,属性名与值可成对输入 |
addDialogControl | 为父对象添加控件,父对象可以为模块的封装对象,也可为group和tab container等能够包容子控件的控件对象 |
封装Simulink子系统
对于未封装的子系统:
maskObj=Simulink.Mask.create(gcbh); maskObj.Type='Custom'; maskObj.Description='This demo displays how to mask a model.'; maskObj.Display='t=0:0.1:10;y=t.^2+1;plot(t,y)'; g_a=maskObj.addParameter('Type','edit','Name','g_a','Prompt','a','Value','0'); g_b=maskObj.addParameter('Type','edit','Name','g_b','Prompt','b','Value','0'); g_a.set('Value','1'); g_b.Value='20';
封装S函数模块
function masktool_neo(block, excelfile) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % This function help to mask parameters and displays into block selected. % MaskNames should not be the same % MaskPrompts, MaskNames, MaskStyles, popupcontents, MaskTabs, MaskCallbackStrings % are written in Excel and this function can automatically transfer them to % the S-function block.Block masked by this tool can not be edited in Mask % Editor. % % block - the block need to be masked % excelfile - parameters saved in the excelfile % % button, image, text, hyperlink, group supported %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % index definition promts_index = 1; names_index = 2; styles_index = 3; popups_index = 4; % tabs_index = 5; callbacks_index = 6; % get data in excelfile [num, str] = xlsread(excelfile); % get mask prompts and saved as cell format promts = str(2:end,promts_index); % get mask names and saved as cell format names = str(2:end,names_index); % change names to MaskVariables format % get mask styles and saved as cell format styles = str(2:end,styles_index); % get mask tab names % tabname = str(2:end, tabs_index); % get TypeOptions typeopts = str(2:end, popups_index); % get callbacks strings callbackstr = str(2:end, callbacks_index); % test if gcbh is masked. If masked , delete the old mask and create a % blank one. maskobj = Simulink.Mask.get(block); if ~isempty(maskobj) maskobj.delete; end maskobj = Simulink.Mask.create(block); % parameter list value p_str = []; % get the object of groupbox "Parameter" % par_obj = maskobj.getDialogControl('ParameterGroupVar'); % add controls according to the styles. len = length(names); for ii = 1:len if ismember(styles{ii}, {'text','group','tab'}) % addDialogControl without callback prop = maskobj.addDialogControl(styles{ii},names{ii}); prop.Prompt = promts{ii}; elseif ismember(styles{ii}, {'pushbutton','hyperlink'}) % addDialogControl for Action controls, they have Callback prop = maskobj.addDialogControl(styles{ii},names{ii}); prop.Prompt = promts{ii}; prop.Callback = callbackstr{ii}; elseif ismember(styles{ii}, 'image') % addDialogControl without Prompt prop = maskobj.addDialogControl(styles{ii},names{ii}); elseif ismember(styles{ii},{'edit','checkbox'}) % 'dial','spinbox','slider' only supported in 2014a and later % addParameter p_str = [p_str, names{ii}, ',']; p = maskobj.addParameter('Type', styles{ii}, 'Prompt', promts{ii},'Name', names{ii}, 'Callback', callbackstr{ii}); elseif ismember(styles{ii}, {'popup','radiobutton'}) % addParameter for parameters that have TypeOptions p_str = [p_str, names{ii}, ',']; expression = '\|'; split_str = regexp(typeopts{ii},expression,'split'); maskobj.addParameter('Type', styles{ii},'TypeOptions', split_str, 'Prompt', promts{ii}, 'Name', names{ii}, 'Callback', callbackstr{ii}); end end % write S-Function name and parameter-list automatically set_param(block, 'FunctionName', excelfile); set_param(block, 'Parameters', p_str(1:end - 1)); disp('Current block is masked automatically.');
11.3 使用GUIDE封装模块
使用S-Function模块结合Level M S函数文件在Simulinnk中实现选择Excel文件,并将其中数据按照采样时间顺序输出的功能。
在模块的对话框中,将数据通过表格展示,并直接将Excel中数据的图像绘制出来。
function [sys,x0,str,ts,simStateCompliance] = sfun_xlsread(t,x,u,flag,g_file_path) switch flag, case 0, [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes(g_file_path); case 1, sys=mdlDerivatives(t,x,u); case 2, sys=mdlUpdate(t,x,u); case 3, sys=mdlOutputs(t,x,u); case 4, sys=mdlGetTimeOfNextVarHit(t,x,u); case 9, sys=mdlTerminate(t,x,u); otherwise DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag)); end function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes(g_file_path) global data len cnt [data, str] = xlsread(g_file_path); len = length(data); sizes = simsizes; sizes.NumContStates = 0; sizes.NumDiscStates = 0; sizes.NumOutputs = 1; sizes.NumInputs = 0; sizes.DirFeedthrough = 0; sizes.NumSampleTimes = 1; sys = simsizes(sizes); x0 = []; str = []; ts = [0,0]; cnt = 0; simStateCompliance = 'UnknownSimState'; function sys=mdlDerivatives(t,x,u) sys = []; function sys=mdlUpdate(t,x,u) sys = []; function sys=mdlOutputs(t,x,u) global data len cnt cnt = cnt + 1; if cnt <= len sys = data(cnt); else sys = data(end); end function sys=mdlGetTimeOfNextVarHit(t,x,u) sampleTime = 1; sys = t + sampleTime; function sys=mdlTerminate(t,x,u) sys = [];
function varargout = sfun_xlsread_gui(varargin) % SFUN_XLSREAD_GUI MATLAB code for sfun_xlsread_gui.fig % SFUN_XLSREAD_GUI, by itself, creates a new SFUN_XLSREAD_GUI or raises the existing % singleton*. % % H = SFUN_XLSREAD_GUI returns the handle to a new SFUN_XLSREAD_GUI or the handle to % the existing singleton*. % % SFUN_XLSREAD_GUI('CALLBACK',hObject,eventData,handles,...) calls the local % function named CALLBACK in SFUN_XLSREAD_GUI.M with the given input arguments. % % SFUN_XLSREAD_GUI('Property','Value',...) creates a new SFUN_XLSREAD_GUI or raises the % existing singleton*. Starting from the left, property value pairs are % applied to the GUI before sfun_xlsread_gui_OpeningFcn gets called. An % unrecognized property name or invalid value makes property application % stop. All inputs are passed to sfun_xlsread_gui_OpeningFcn via varargin. % % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one % instance to run (singleton)". % % See also: GUIDE, GUIDATA, GUIHANDLES % Edit the above text to modify the response to help sfun_xlsread_gui % Last Modified by GUIDE v2.5 26-Jul-2014 19:44:47 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; gui_State = struct('gui_Name', mfilename, ... 'gui_Singleton', gui_Singleton, ... 'gui_OpeningFcn', @sfun_xlsread_gui_OpeningFcn, ... 'gui_OutputFcn', @sfun_xlsread_gui_OutputFcn, ... 'gui_LayoutFcn', [] , ... 'gui_Callback', []); if nargin && ischar(varargin{1}) gui_State.gui_Callback = str2func(varargin{1}); end if nargout [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); else gui_mainfcn(gui_State, varargin{:}); end % End initialization code - DO NOT EDIT % --- Executes just before sfun_xlsread_gui is made visible. function sfun_xlsread_gui_OpeningFcn(hObject, eventdata, handles, varargin) % This function has no output args, see OutputFcn. % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % varargin command line arguments to sfun_xlsread_gui (see VARARGIN) % Choose default command line output for sfun_xlsread_gui handles.output = hObject; % Update handles structure guidata(hObject, handles); % UIWAIT makes sfun_xlsread_gui wait for user response (see UIRESUME) % uiwait(handles.figure1); % --- Outputs from this function are returned to the command line. function varargout = sfun_xlsread_gui_OutputFcn(hObject, eventdata, handles) % varargout cell array for returning output args (see VARARGOUT); % hObject handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % Get default command line output from handles structure varargout{1} = handles.output; % --- Executes on button press in pushbutton1. function pushbutton1_Callback(hObject, eventdata, handles) % hObject handle to pushbutton1 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) close(gcf); % --- Executes on button press in pushbutton2. function pushbutton2_Callback(hObject, eventdata, handles) % hObject handle to pushbutton2 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) close(gcf); % --- Executes on button press in pushbutton3. function pushbutton3_Callback(hObject, eventdata, handles) % hObject handle to pushbutton3 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) disp('Help button is pressed. User can supply help file themselves.'); % --- Executes on button press in pushbutton4. function pushbutton4_Callback(hObject, eventdata, handles) % hObject handle to pushbutton4 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) [filename, pathname] = uigetfile({'*.xls','*.xlsx'}, 'Select an Excel file'); if isequal(filename,0) set_param(gcbh, 'g_file_path', ''); set(handles.edit1, 'string', ''); disp('User selected Cancel'); return; else file_path = fullfile(pathname, filename); set_param(gcbh, 'g_file_path', file_path); set(handles.edit1, 'string', file_path); end [data, str] = xlsread(file_path); set(handles.uitable1, 'data', data); axes(handles.axes1); bar(data, 'g'); function edit1_Callback(hObject, eventdata, handles) % hObject handle to edit1 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % Hints: get(hObject,'String') returns contents of edit1 as text % str2double(get(hObject,'String')) returns contents of edit1 as a double % --- Executes during object creation, after setting all properties. function edit1_CreateFcn(hObject, eventdata, handles) % hObject handle to edit1 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called % Hint: edit controls usually have a white background on Windows. % See ISPC and COMPUTER. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end