Simulink仿真入门到精通(十) S函数
10.1 S函数概述
S函数也称为Simulink中的系统函数,是用来描述模块的Simulink宏函数,支持M、C等多种语言。当Simulink默认的模块不能满足用户的需求时,用户可以通过S函数自己打造一个模块,实现自定义的算法或期待的动作。
10.2 S函数的类型
- S函数有多种类型,按照语言分类有M、C、C++、Fortran等编写的;
- 按照所支持功能多少分类,包括Level1和Level2;
- 按照执行方式分类,可分为直接解释运行的M S函数和编译为Mex文件后执行的C Mex S函数。
Level1 M S函数输入输出端口最多位1且数据维数固定,Level2 M S函数的输入输出端口个数可以为多个,数据维数也可以动态改变。
编写一个既能用于仿真又能用于代码生成的算法时,需要给S函数编写同名的TLC文件。
由于M语言需要调用MATLAB解释器,故C Mex S函数运行速度比M S函数更快。
10.3 S函数的要素
一个Simulink模块包括输入、输出以及内部的状态量。除了3要素之外,还有一个无处不在的时间量。
所谓状态量,根据系统性质分为连续系统中的微分量和离散系统中的差分量。
dx/dt=f(t,x,u)
y=g(t,x,u)
10.4 S函数的组成及执行顺序
执行顺序:
- main
- {
- 初始化模型;
- 计算下一个采样时间点(大步长);
- while(未到达仿真终止时间)
- {
- 计算模块的输出;
- 更新离散状态量;
- if(此模型带有连续状态模块)
- {
- here:计算微分;
- 计算模块的输出;
- if(精度未达标)
- goto here;
- 过零检测;
- 计算写一个采样时间点(大步长);
- }
- }
执行仿真终止动作;- }
仿真运行时,模型首先要对模块进行初始化,这个过程包括模块的实例化:输入/输出端口、信号唯独、端口数据类型及采样时间等的确定,模块参数的获取及个数检查,并决定模块的执行顺序等。
- 实例化:Simulink标准库中提供的模块类似于C++等面向对象语言中的一个类,每当模块被拷贝或拖曳到模型中时,就相当于创建了这个类的一个对象,继承了这个类的属性并载入了默认的构造函数方法对其参数、端口等各个属性进行了初始化工作。
- 信号维度:一根信号线传递的数据不仅可以是标量,也可以是一个向量或矩阵,一个模块的输出端口将具有这个数据维度的信号传递给相连的信号线然后再传递给下一个模块的输入端口,这些都是需要在初始化阶段确定下来的。
- 端口数据类型:模块的输出/输出数据是浮点数还是固定点数,是8为、16位、32为或64位,有无符号,内建类型或者用户自定义类型,这些也在初始化阶段指定。
- 采样时间:对于Simulink模型来说,解算器中的一个步长决定了整个模型最小的采样时间间隔。
- 模型中模块的执行顺序:当众多模块同时存在于一个模型中时,Simulink是有明确的顺序优先度的。
S函数子方法表:
子方法 | 作用说明 |
初始化 | 在第一个采样时间的仿真之前运行的函数,用来初始化模块,包括设定输入/输出端口的个数和维数,输入是否直接馈入,参数个数设定采样时间,当使用工作向量时还需要为其分配存储空间 |
下一个采样时间点计算 | 根据模型解算器的算法求得下一个采样时间点,通常用于变步长模块 |
输出函数计算 | 在每一个major step计算模型所有的输出口的输出值 |
离散状态更新 | 在每一个major step都进行一次离散状态的更新计算,在输出函数之后 |
积分计算 | 如果模型具有连续状态,才采取此方法。将major step分隔为数个minor step,在每一个minor step里进行一次输出函数与积分计算。积分计算主要用来更新连续状态。当模型中存在非采样过零检测时,还会在minor step中进行过零检测 |
模型终止 | 当模型终止仿真时调用的子函数,用于清除不用的变量,释放内存空间等动作 |
10.5 使用不同语言编写S函数
不同S函数的特点:
S函数 | 特点 |
Level1 M | 支持简单的MATLAB接口及少数的API |
Level2 M | 支持扩展的S函数API及代码生成功能,使用场合更加广泛 |
C MEX | 提供更灵活的编程方式,即可手写C代码也可以调用既存的C/C++或Fortran代码。要求掌握很多C MEX S函数API用法及TLC代码编写方法,才能够制定具有代码生成功能的C MEX S函数 |
10.5.1 Level1 M S函数
[sys,x0,str,ts]=f(t,x,u,flag,p1,p2,...)
其中f是S函数的函数名,Simulink会在仿真过程中的每个步长内多次调用f。
flag的值随着仿真过程自动变化,其值对应的S函数子方法如下:
flag值 | Level1 M S函数子方法名 | 说明 |
0 | mdlInitializeSizes | 定义S函数的基本属性,如输入/输出维数、连续/离散状态变量个数、采样时间、以及输入是否为直接馈入等 |
1 | mdlDerivatives | 连续状态变量的微分函数,这里通常通过给定的微分计算表达式,通过积分计算得到状态变量的值 |
2 | mdlUpdate | 更新离散状态变量 |
3 | mdlOutputs | 计算S函数的输出 |
4 | mdlGetTimeOfNextVarHit | 仅在变离散采样时间情况下使用,用于计算下一个采样时时刻的绝对时间,若模块不是变步长此函数不会执行 |
9 | mdlTerminate | 在仿真结束时执行一些必要的动作,如清除临时变量,或显示提示信息等 |
说明——直接馈入:
如果S函数的输出y或采样时间t与输入u有直接联系,就是直接馈入;否则不存在直接馈入情况。如果若干直接馈入的模块通过反馈构成了一个环形,就会出现所谓的代数环。
Level1 M S输入参数表:
输入参数 | 功能 |
t | 当前时刻的仿真时间 |
x | 状态变量向量 |
u | 输入向量 |
pn,n=1,2,3,... | 用户自定义参数,数目不定 |
Level1 M S输出参数表:
输出参数 | 功能 |
sys | 通用输出参数,根据flag的值来决定返回值,比如flag=3时返回S函数的输出信号;flag=2时则返回更新后的离散状态变量的值;flag=1时根据设置的微分值积分计算出连续状态变量的值 |
x0 | 状态变量的初始值,仅在flag=0时有效,其余情况被忽略 |
str | 保留变量,用户只能将其初始化为[ ] |
ts | S函数的采样时间,由一个二维的数组表示 |
ts=[m,n]中m为模块的采样时间周期,表示每隔多长时间采样一次,n为采样时间的偏移量,表示与采样时间周期所表示的时刻点的偏差时间。
例如:
采样时间表示 | 含义 |
[0,0] | 连续采样时间 |
[-1,0] | 继承S函数输入信号或父层模型的采样时间 |
[0.5,0.1] | 离散采样时间,从0.1s开始每0.5s采样一次 |
[0.25,0;1,0.1] | [0,0.1,0.25,0.5,0.75,1,1.1,...] |
示例:
dx1/dt=-0.5572x1-0.7814x2+u1-u2;
dx2/dt=0.7814x1+2u2;
y=1.9691x1+6.4493x2;
由方程可知:
- A=[-0.5572,-0.7814;0.7814,0];
- B=[1,-1;0,2];
- C=[1.9691,6.4493];
- function [sys,x0,str,ts,simStateCompliance] = sfun_state01(t,x,u,flag,A,B,C)
- switch flag,
- case 0,
- [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;
- case 1,
- sys=mdlDerivatives(t,x,u);
- case 2,
- sys=mdlUpdate(t,x,u,A,B);
- case 3,
- sys=mdlOutputs(t,x,u,C);
- 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
- sizes = simsizes;
- sizes.NumContStates = 0;
- sizes.NumDiscStates = 2;
- sizes.NumOutputs = 1;
- sizes.NumInputs = 2;
- sizes.DirFeedthrough = 0;
- sizes.NumSampleTimes = 1;
- sys = simsizes(sizes);
- x0 = [0 0]';
- str = [];
- ts = [0,0];
- simStateCompliance = 'UnknownSimState';
- function sys=mdlDerivatives(t,x,u)
- sys = [];
- function sys=mdlUpdate(t,x,u,A,B)
- % update state variable
- sys = A * x + B * u;
- function sys=mdlOutputs(t,x,u,C)
- % update output
- sys = C * x;
- function sys=mdlGetTimeOfNextVarHit(t,x,u)
- sampleTime = 1;
- sys = t + sampleTime;
- function sys=mdlTerminate(t,x,u)
- sys = [];
示例:积分
- function [sys,x0,str,ts,simStateCompliance] = int_hyo(t,x,u,flag)
- switch flag,
- case 0,
- [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;
- 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
- sizes = simsizes;
- sizes.NumContStates = 1;
- sizes.NumDiscStates = 0;
- sizes.NumOutputs = 1;
- sizes.NumInputs = 1;
- sizes.DirFeedthrough = 0;
- sizes.NumSampleTimes = 1; % at least one sample time is needed
- sys = simsizes(sizes);
- x0 = [0];
- str = [];
- ts = [0 0];
- simStateCompliance = 'UnknownSimState';
- function sys=mdlDerivatives(t,x,u)
- sys = u;
- function sys=mdlUpdate(t,x,u)
- sys=[];
- function sys=mdlOutputs(t,x,u)
- sys=x;
- function sys=mdlGetTimeOfNextVarHit(t,x,u)
- sampleTime = 1; % Example, set the next hit to be one second later.
- sys = t + sampleTime;
- function sys=mdlTerminate(t,x,u)
- sys = [];
10.5.2 Level2 M S函数
Level2 M S函数使得用户能够使用MATLAB语言来编写支持多个输入/输出端口的自定义模块,并且每个端口都能够支持包括矩阵在内的Simulink支持的所有数据类型。
1. Setup子方法
Setup子方法是Level2 M S函数体中唯一调用的语句,对模块的属性和其他子方法进行初始化,Setup子方法类似Level1 M S函数中mdlInitializeSizes子方法的功能,并且相比之下功能更加强大,在Setup中不仅可以设置多输入多输出,而且每个输出的端口信号的维数可以是标量数或矩阵甚至是可变维数,另外S函数的其他子方法也是通过Setup子方法进行注册的,因此Setup可以成为Level2 M S函数的根本。
Setup子方法实现以下功能:
- 设定模块输入输出端口的个数;
- 设定每一个端口的数据类型、数据维度、实数复数性和采样时间等;
- 规定模块的采样时间;
- 设定S函数参数的个数;
- 注册S函数的子方法(将子方法函数的句柄传递到实时对象的RegBlockMethod函数的对应属性中)。
S函数实时对象的属性列表:
实时对象属性成员 | 说明 |
NumDialogPrms | 模块GUI参数个数 |
NumInputPorts | 输入端口数 |
NumOutputPorts | 输出端口数 |
BlockHandle | 模块句柄,只读 |
CurrentTime | 当前仿真时间,只读 |
NumContStates | 连续状态变量数目 |
NumDworkDiscStates | 离散状态变量数目 |
NumRuntimePrms | 运行时参数个数 |
SampleTimes | 产生输出的模块的采样时间 |
NumDworks | 离散工作向量个数 |
函数端口的属性列表:
属性端口名 | 说明 |
Dimensions | 端口数据维度 |
DatatypeID/Datatype | 端口数据类型,可以通过ID号指定也可以直接指定数据类型名 |
Complexity | 端口数据是否为复数 |
DirectFeedthrough | 端口数据是否直接馈入 |
DimensionsMode | 端口维数是固定或可变的(fixed/variable) |
实时对象的方法列表:
实时对象方法 | 说明 |
ContStates | 获取模块的连续状态 |
DataTypeIsFixedPoint | 判断数据类型是否为固定点数 |
DatatypeName | 获取数据类型的名称 |
DatatypeSize | 获取数据类型大小 |
Derivatives | 获取连续状态的微分 |
DialogPrm | 获取GUI中的参数 |
Dwork | 获取Dwork向量 |
FixedPointNumericType | 获取固定点数据类型的操作 |
InputPort | 获取输入端口 |
OutputPort | 获取输出端口 |
RuntimePrm | 获取运行时参数 |
其他子方法列表:
子方法名 | 说明 |
PostPropagationSetup | 设置工作向量及状态变量的函数(可选) |
InitializeConditions | 在仿真开始时被调用的初始化函数(可选) |
Start | 在模型运行仿真时调用一次,用来初始化状态变量和工作向量(可选) |
Outputs | 在每个步长里计算模型输出 |
Updata | 在每个步长里更新离散状态变量的值(可选) |
Derivatives | 在每个步长里更新连续状态变量的微分值(可选) |
Terminate | 在仿真结束时调用,用来清除变量内存 |
2. PostPropagationSetup
PostPropagationSetup子方法是用来初始化Dwork工作向量的方法,规定Dwork向量的个数及每个向量的维数、数据类型、离散状态变量的名字和虚拟性,以及是否作为离散变量使用。
Dwork向量是Simulink分配给模型中每个S函数实例的存储空间块。当不同S函数块之间需要通过全局变量或者静态变量进行数据交互时,必须在S函数中使用Dwork向量来进行变量存储。
Dwork属性列表:
名称 | 含义 |
Name | 名字 |
Dimensions | 数据维数 |
DatetypeID | 数据类型 |
Complexity | 是否复数 |
UsedAsDiscState | 是否作为离散变量使用 |
代表不同数据类型的ID(整数):
数据类型 | ID |
ingerited | -1 |
double | 0 |
single | 1 |
int8 | 2 |
uint8 | 3 |
int16 | 4 |
uint16 | 5 |
int32 | 6 |
uint32 | 7 |
boolean或定点类型 | 8 |
3. InitializeConditions/Start子方法
InitializeConditions子方法可以用来初始化状态变量或者Dwork工作向量的值。
Start子方法跟InitializeConditions子方法功能一致,但仅仅在仿真开始的时候初始化一次,而S函数模块放置在是能子系统中时其InitializeConditions子方法在每次子系统被使能时都会被调用。
4. Output子方法
Output子方法跟Level1 M S函数的mdlOutputs子方法作用一样,用于计算S函数的输出。
5. Updata子方法
Updata子方法跟Level1 M S函数中mdlUpdata子方法作用相同,用于计算离散状态变量的值。
6. Derivatives子方法
Derivatives子方法跟Level1 M S函数中的mdlDerivatives子方法作用相同,用于计算并更新连续状态变量的值。
7. Terminate子方法
S函数的收尾工作放在Terminate子方法中进行,如存储空间的释放,变量的删除等。
阿布罗狄:
艾欧里亚:
- m1=imread('阿布罗狄.jpg');
- m1=m1(:,:,1);
- m2=imread('艾欧里亚.jpg');
- m2=m2(:,:,1);
- function sfun_image_merge(block)
- setup(block);
- function setup(block)
- block.BlockHandle
- % Register number of ports
- block.NumInputPorts = 2;
- block.NumOutputPorts = 0;
- % Setup port properties to be inherited or dynamic
- block.SetPreCompInpPortInfoToDynamic;
- % Override input port properties
- block.InputPort(1).Dimensions = [375 500];
- block.InputPort(1).DatatypeID = 3; % uint8
- block.InputPort(1).Complexity = 'Real';
- block.InputPort(1).DirectFeedthrough = false;
- block.InputPort(2).Dimensions = [375 500];
- block.InputPort(2).DatatypeID = 3; % uint8
- block.InputPort(2).Complexity = 'Real';
- block.InputPort(2).DirectFeedthrough = false;
- % Register parameters
- block.NumDialogPrms = 0;
- % Register sample times
- % [0 offset] : Continuous sample time
- % [positive_num offset] : Discrete sample time
- %
- % [-1, 0] : Inherited sample time
- % [-2, 0] : Variable sample time
- block.SampleTimes = [0 0];
- % Specify the block simStateCompliance. The allowed values are:
- % 'UnknownSimState', < The default setting; warn and assume DefaultSimState
- % 'DefaultSimState', < Same sim state as a built-in block
- % 'HasNoSimState', < No sim state
- % 'CustomSimState', < Has GetSimState and SetSimState methods
- % 'DisallowSimState' < Error out when saving or restoring the model sim state
- block.SimStateCompliance = 'DefaultSimState';
- block.RegBlockMethod('Terminate', @Terminate); % Required
- function Terminate(block)
- imshow((block.InputPort(1).data + block.InputPort(2).data) / 2);
好丑!看不出什么效果。
再试一次:
融合后:
原来核心语句在这里:
- imshow((block.InputPort(1).data + block.InputPort(2).data) / 2);
10.5.3 C MEX S函数
S函数支持的语言除了MATLAB/Simulink自身环境的M语言之外,最常用的就是C语言了。使用C语言编写S函数成为C Mex Sh函数,相比于解释运行的M S函数,在仿真过程中不需要反复调用MATALB解释器,而是在运行前将.c文件编译成mexw32/mexw64类型的可执行文件,运行速度和效率上有明显优势;并且C语言拥有编程语言生的灵活性优势。
C Mex S函数的运行机制与M S函数是一致的,包括常用的初始化、更新、微分计算、输出和终止等子方法,这些子方法几乎可以与Level2 M S函数的子方法一一对应起来。但是由于语言的不同,所使用的数据结构形式上也有区别。
对应关系:
C Mex S函数子方法 | Level2 M S函数子方法 | 子方法功能 |
mdlInitializeSizes | Setup | 模块属性初始化 |
mdlDerivatices | Derivatives | 更新连续状态变量的微分值 |
mdlInitializeConditions | InitializeConditions | 初始化工作向量的状态值 |
mdlOutputs | Outputs | 计算模块的输出 |
mdlSetWorkWidths | PostPropagationSetup | 当S函数模块存在于使能子系统中时,每次子系统被使能均进行工作向量属性的初始化工作 |
mdlStart | Start | 在仿真开始时初始化工作向量及状态变量的属性 |
mdlTerminate | Terminate | 在仿真终止时所调用的子方法 |
mdlUpdate | Updata | 更新离散状态变量的子方法 |
mdlRTW | WriteRTW | 将S函数中获取到的GUI参数变量值写入到rtw文件中以使TLC文件用来生成代码的子方法 |
1. C Mex S函数的构成
- 最开头必须定义的两个宏:C Mex S函数名及C Mex S函数的等级。
- 头文件包含部分C Mex S函数核心数据结构simstruct类型的声明及其他库文件,另外用户根据使用需要也可以包含其他头文件。
- 参数对话框访问宏函数的定义。
- 紧接着定义C Mex S函数的各个子方法。
- S函数必须根据使用情况包含必要的源文件和头文件,从而将该S函数文件与Simulink或Simulink Coder产品进行连接。
2. C Mex S函数的编译
编译型语言编写的程序执行之前,需要一个专门的编译过程,把程序编译成为机器语言的文件,如exe文件或mexw32/menw64文件,运行时不需要重新翻译。
- >> mex -setup
- MEX 配置为使用 'Microsoft Visual C++ 2010 (C)' 以进行 C 语言编译。
- Warning: The MATLAB C and Fortran API has changed to support MATLAB
- variables with more than 2^32-1 elements. In the near future
- you will be required to update your code to utilize the
- new API. You can find more information about this at:
- http://www.mathworks.com/help/matlab/matlab_external/upgrading-mex-files-to-use-64-bit-api.html.
- 要选择不同的语言,请从以下选项中选择一种命令:
- mex -setup C++
- mex -setup FORTRAN
- >> mex -setup C++
- MEX 配置为使用 'Microsoft Visual C++ 2010' 以进行 C++ 语言编译。
- >> mex sfun_c_filter.c
- 使用 'Microsoft Visual C++ 2010 (C)' 编译。
- MEX 已成功完成。
3. C Mex S函数的应用
- //sfun_c_filter.c
#define S_FUNCTION_NAME sfun_c_filter- #define S_FUNCTION_LEVEL 2
- #include "simstruc.h"
- #define COEF_IDX 0
- #define COEF(S) mxGetScalar(ssGetSFcnParam(S,COEF_IDX))
- /*================*
- * Build checking *
- *================*/
- /* Function: mdlInitializeSizes ===============================================
- * Abstract:
- * Setup sizes of the various vectors.
- */
- static void mdlInitializeSizes(SimStruct *S)
- {
- ssSetNumSFcnParams(S, );
- if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
- return; /* Parameter mismatch will be reported by Simulink */
- }
- if (!ssSetNumInputPorts(S, )) return;
- ssSetInputPortWidth(S, , DYNAMICALLY_SIZED);
- ssSetInputPortDirectFeedThrough(S, , );
- if (!ssSetNumOutputPorts(S,)) return;
- ssSetOutputPortWidth(S, , DYNAMICALLY_SIZED);
- ssSetNumDWork(S, );
- ssSetDWorkWidth(S, , DYNAMICALLY_SIZED);
- ssSetNumSampleTimes(S, );
- /* specify the sim state compliance to be same as a built-in block */
- ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);
- ssSetOptions(S,
- SS_OPTION_WORKS_WITH_CODE_REUSE |
- SS_OPTION_EXCEPTION_FREE_CODE |
- SS_OPTION_USE_TLC_WITH_ACCELERATOR);
- }
- /* Function: mdlInitializeSampleTimes =========================================
- * Abstract:
- * Specifiy that we inherit our sample time from the driving block.
- */
- static void mdlInitializeSampleTimes(SimStruct *S)
- {
- ssSetSampleTime(S, , INHERITED_SAMPLE_TIME);
- ssSetOffsetTime(S, , 0.0);
- ssSetModelReferenceSampleTimeDefaultInheritance(S);
- }
- #define MDL_INITIALIZE_CONDITIONS
- /* Function: mdlInitializeConditions ========================================
- * Abstract:
- * Initialize both discrete states to one.
- */
- static void mdlInitializeConditions(SimStruct *S)
- {
- real_T *x = (real_T*) ssGetDWork(S,);
- x[] = 0.0; // initial to 0.0
- }
- /* Function: mdlOutputs =======================================================
- * Abstract:
- * y = 2*u
- */
- static void mdlOutputs(SimStruct *S, int_T tid)
- {
- int_T i;
- InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,);
- real_T *y = ssGetOutputPortRealSignal(S,);
- int_T width = ssGetOutputPortWidth(S,);
- real_T *x = (real_T*) ssGetDWork(S,);
- real_T Lc = COEF(S);
- for (i = ; i < width; i++)
- {
- y[i] = (*uPtrs[i] - x[i]) * Lc + x[i];
- }
- /* save the current output as the DWork Vector */
- for (i=; i<width; i++) {
- x[i] = y[i];
- }
- }
- /* Function: mdlTerminate =====================================================
- * Abstract:
- * No termination needed, but we are required to have this routine.
- */
- static void mdlTerminate(SimStruct *S)
- {
- }
- #ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
- #include "simulink.c" /* MEX-file interface mechanism */
- #else
- #include "cg_sfun.h" /* Code generation registration function */
- #endif
- g_coef=0.005;
4. C Mex S函数的自动生成
Simulink提供了两个工具箱帮助用户快速生成C Mex S函数。
- S-Function Builder:根据用户的配置自动生成C Mex S函数;
- Legacy Code Tool:能够将既存的或者用户自定义的C代码打包生成内联的C Mex S函数,并且能够生成嵌入式C代码应用于嵌入式目标芯片。
(1)S-Function Builder
3个部分:
- S函数名称及参数列表显示部分;
- S函数端口及参数的结构树形图;
- 与S函数各个子方法对应的配置界面。
配置界面与S函数子方法的对应关系:
配置界面 | 对应的S函数子方法 |
Initialization | mdlInitializationSizes中状态变量和mdlInitializeSampleTimes中采样时间的设定及mdlInitializeConditions中中状态变量初始值的确定 |
Data Properties | mdlInitialize中输入输出端口和参数的个数、数据类型 |
Libraries | 无对应子方法,此处填入编译用户代码时所需的头文件 |
Outputs | mdlOutputs子方法 |
(Continous) Derivatives | mdlDerivatives子方法 |
(Discrete) Update | mdlUpdate子方法 |
Build Info | 无子方法对应,用来显示编译信息,并提供给用户功能选项,生成C代码时可以选择是否生成TLC文件,是否同时编译C文件为mex文件等 |
Initialization
- Number of discrete/continuous states:S函数中需要设置几个离散/连续状态变量,这些状态变量的初始值通过Discrete/Continuous states IC配置。当多个状态变量存在时,使用向量形式给出,如给出3个连续/离散状态变量的初始值[0,0,0],元素个数必须与初始化的状态变量个数相同;
- Sample mode:提供了3种采样时间,
- Inherited:S函数继承输入端口的采样时间;
- Continuous:S函数采用连续采样时间,在每个步长更新输出值;
- Discrete:S函数采用离散采样时间,Sample time value设置采样时间间隔。
Data Properties
Data Properties将S函数相关的数据量和信息分散在4个子页面上进行配置。
左侧提供了4个按钮,为端口和参数的添加、删除、上移和下移操作。
- Input ports:输入端口的名称、维数、数据行列、实数虚数性和总线类型设置;
- Output ports:输出端口的名称、维数、数据行列、实数虚数性和总线类型设置;
- Parameters:增加参数并设置其名称、数据类型和实数虚数性。
注:Dimensions下拉菜单支持1-D和2-D数据,Rows中输入数据的行数,-1表示行数是动态的,Columns仅在2-D时有效。
- Data type attributes:对输入/输出端口的数据类型进行设定,包括内建类型和固定点类型。当选择固定点类型时,可对数据类型的详细信息进行配置,包括数据字长(Word length)和小数位数(Fraction length)等。
Library
Library页面中主要用于添加头文件、外部源文件、用户自定义代码相关文件和函数声明。
- Library/Object/Source files(One per line):当S函数的子方法配置中使用了外部的库、目标文件或源文件时,需要将库文件、目标文件和源文件的全路径写在此对话框中。如果这些文件存放在当前路径之下,则只需要写入文件名即可。
如:customfunctions.lib、userfunctions.obj、freesource.c。
用户可以在此处通过关键字LIB_PATH、INC_PATH、SRC_PATH添加搜索路径,在关键字之后给出文件路径,S-Function Builder会自动选择到关键字后的路径中搜索相关文件。
如:
- SRC_PATH D:\externalsource
- LIB_PATH $ MATLABROOT\customobjs
- INC_PATH C:\customfolder
- customfunctions.lib
- Includes:当用户自定义代码出现在S-Function Builder的任何配置中时,所涉及的头文件、函数声明、变量和宏定义等都应该在此使用#include语句进行包含。如果所包含的头文件是标准C语言库,使用尖括号,如#include<math.h>;如果所包含的头文件是用户自定义代码,使用双引号,如#include "my_device.h"。特别的,当被包含的头文件不在当前路径时,需要在Library/Object/Source files(One per line)对话框中使用INC_PATH来指定这个头文件所在的文件路径。
- External functions Declaretion:当S-Function Builder中需要在状态变量和Outputs子方法中调用某些外部函数计算,并且这些函数既不是Simulink自带的,也不被Includes中列出的头文件所包含时,在此处进行函数声明。
Outputs
Outputs子页面中输入的内容就是S函数Outputs子方法函数体内容,C Mex S函数的输入/输出端口数据的部分代码可以省略,直接使用输入/输出端口名和下标索引号即可作为输入/输出变量,并规定它们之间的关系。
输入的直接馈入在页面左下角的勾选框设置,勾选Inputs are needed in the output function(direct feedthrough)后,即可在对话框中使用输入端口变量名。
用户在该对话框中编写的代码将在编译时打包为一个函数sfun_Outputs_wrapper,插入到函数体中,再在C Mex S函数的mdlOutputs中进行调用。
(Continous) Derivatives
用户可以填入计算连续状态变量的代码,连续状态变量按照维数索引号,可以使用xC[0],xC[1]或者dx[0],dx[1]表示,这些变量必须是double类型。输入/输出端口号和参数必须在Data Properties中定义过的端口名和参数变量名。
此对话框中所填入的内容被打包为一个函数sfun_Derivatives_wrapper函数,再在mdlDerivatives中调用。
(Discrete) Update
用于输入mdlUpdate子方法对应的内容,无需使用宏函数获取输入/输出端口、参数和离散状态变量的值。离散状态变量使用xD[0],xD[1]等引用即可。输入/输出端口号和参数必须在Data Properties中定义过的端口名和参数变量名。
此对话框中所填入的内容被打包为一个函数sfun_Update_wrapper函数,再在mdlUpdate中调用。
Build Info
用于显示编译C代码和可执行文件时的编译信息。
Build options:
Build options | 作用说明 |
Show compile steps | 在Compilation diagnostics框记录每一个编译步骤信息 |
Generate wrapper TLC | 生成TLC文件以支持代码生成或加速仿真模式 |
Enable access to SimStruct | 使得Outputs、Derivatives、Updates 3个页面的代码可以使用SimStruct类提供的宏函数 |
Create a debuggable MEX-file | 生成mex文件时包含调试信息 |
Save code only | 只生成C Mex S函数代码不生成MEX文件 |
例:使用S-Function Builder生成一阶滤波器
Y(t)=(U(t)-Y(t-1)) ×Lc+Y(t-1)
离散状态变量:1个;
输入:u,输出:y,Dimen为1-D,Row为-1;
double型参数filter_coef,值为0.05;
Outputs:
- y[0]=(u[0]-xD[0])*filter_coef[0]+xD[0];
Update:
- xD[0]=y[0];
Build!
得到:
报错:
错误使用 mex,未找到支持的编译器。
参考:
https://ww2.mathworks.cn/matlabcentral/answers/101105-how-do-i-install-microsoft-windows-sdk-7-1#answer_110453
将以下两个文件从C:\Users\lenovo\AppData\Roaming\MathWorks\MATLAB\R2014a拷贝到C:\Users\lenovo\AppData\Roaming\MathWorks\MATLAB\R2018a,获得成功。
(2)Legacy Code Tool
能够将既存的C/C++代码转换为Simulink模型中可以使用的C Mex S函数,同时也能生成TLC文件。
Legacy Code Tool将用户既存的算法代码插入到C Mex S函数的Outputs子方法中,用户需要提供足够的信息,这些信息包括:为MATLAB安装一个C编译器,S函数名,既存算法的函数原型,及为了编译既存C文件所需要的其他头文件、源文件及其存放路径。
legacy_code命令可以完成以下几件事情:
- 根据既有C代码初始化Legacy Code Tool的数据结构;
- 生成可用于仿真的C Mex S函数;
- 将生成的S函数编译链接为动态可执行文件(mex文件);
- 生成一个封装起来的模块来调用S函数;
- Simulink Coder组件会生成S函数的模块级TLC文件。
LCT(Legacy Code Tool)的使用流程:
通常使用'initialize'作为legacy_code的参数初始化一个LCT对象:
- >> lct_spec=legacy_code('initialize')
- lct_spec =
- 包含以下字段的 struct:
- SFunctionName: ''
- InitializeConditionsFcnSpec: ''
- OutputFcnSpec: ''
- StartFcnSpec: ''
- TerminateFcnSpec: ''
- HeaderFiles: {}
- SourceFiles: {}
- HostLibFiles: {}
- TargetLibFiles: {}
- IncPaths: {}
- SrcPaths: {}
- LibPaths: {}
- SampleTime: 'inherited'
- Options: [1×1 struct]
LCT对象的各个属性:
属性名 | 作用说明 |
SFunctionName | 所生成S函数的名字 |
InitializeConditionsFcnSpec | 应用于InitializeConditions子方法中的既存C代码函数原型 |
OutputFcnSpec | 应用于OutputFcn子方法中的既存C代码函数原型 |
StartFcnSpec | 应用于StartFcn子方法中的既存C代码函数原型 |
TerminateFcnSpec | 应用于TerminateFcn子方法中的既存C代码函数原型 |
HeaderFiles | 声明既存C函数及其他需要编译的头文件 |
SourceFiles | 定义既存C函数及其他需要编译的源文件 |
HostLLibFiles/TargetLibFiles | 主机/目标端编译C文件所依赖的库文件 |
IncPaths | LCT搜索路径寻找编译需要的头文件 |
SrcPaths | LCT搜索路径寻找编译需要的源文件 |
LibPaths | Lct搜索路径寻找编译需要的库和目标文件 |
SampleTime | 采样时间 |
Options | 控制S函数Options的选项 |
- legacy_code('help'):打开LCT工具的详细使用说明的帮助文档;
- legacy_code('sfcn_cmex_generate',lct_spec):根据lct_spec生成S函数源文件;
- legacy_code('compile',lct_spec):对生成的S函数进行编译链接;
- legacy_code('slblock_generate',lct_spec,modename):生成一个封装模块调用生成的S函数,并自动将此模块添加到名为modename的模型文件里;
- legacy_code('sfcn_tlc_generate',lct_spec):生成S函数配套的TLC文件,用于加速仿真模型或通过Simulink模型生成代码;
- legacy_code('rtwmakecfg_generate',lct_spec):生成rtwmakecfg.m文件,此文件是用于生成适用于当前lct_spec对象的makefile的M脚本。
例:使用Legacy Code Tool集成正弦C代码
- //EmMath.c
- #include"EmMath.h"
- const unsigned short SinTbl[] = {0x0000, //
- 0x0019, 0x0032, 0x004B, 0x0064, 0x007D, 0x0096, 0x00AF, 0x00C8, 0x00E2, 0x00FB,//
- 0x0114, 0x012D, 0x0146, 0x015F, 0x0178, 0x0191, 0x01AA, 0x01C3, 0x01DC, 0x01F5,//
- 0x020E, 0x0227, 0x0240, 0x0258, 0x0271, 0x028A, 0x02A3, 0x02BC, 0x02D4, 0x02ED,//
- 0x0306, 0x031F, 0x0337, 0x0350, 0x0368, 0x0381, 0x0399, 0x03B2, 0x03CA, 0x03E3,//
- 0x03FB, 0x0413, 0x042C, 0x0444, 0x045C, 0x0474, 0x048C, 0x04A4, 0x04BC, 0x04D4,//
- 0x04EC, 0x0504, 0x051C, 0x0534, 0x054C, 0x0563, 0x057B, 0x0593, 0x05AA, 0x05C2,//
- 0x05D9, 0x05F0, 0x0608, 0x061F, 0x0636, 0x064D, 0x0664, 0x067B, 0x0692, 0x06A9,//
- 0x06C0, 0x06D7, 0x06ED, 0x0704, 0x071B, 0x0731, 0x0747, 0x075E, 0x0774, 0x078A,//
- 0x07A0, 0x07B6, 0x07CC, 0x07E2, 0x07F8, 0x080E, 0x0824, 0x0839, 0x084F, 0x0864,//
- 0x087A, 0x088F, 0x08A4, 0x08B9, 0x08CE, 0x08E3, 0x08F8, 0x090D, 0x0921, 0x0936,//
- 0x094A, 0x095F, 0x0973, 0x0987, 0x099C, 0x09B0, 0x09C4, 0x09D7, 0x09EB, 0x09FF,//
- 0x0A12, 0x0A26, 0x0A39, 0x0A4D, 0x0A60, 0x0A73, 0x0A86, 0x0A99, 0x0AAB, 0x0ABE,//
- 0x0AD1, 0x0AE3, 0x0AF6, 0x0B08, 0x0B1A, 0x0B2C, 0x0B3E, 0x0B50, 0x0B61, 0x0B73,//
- 0x0B85, 0x0B96, 0x0BA7, 0x0BB8, 0x0BC9, 0x0BDA, 0x0BEB, 0x0BFC, 0x0C0C, 0x0C1D,//
- 0x0C2D, 0x0C3E, 0x0C4E, 0x0C5E, 0x0C6E, 0x0C7D, 0x0C8D, 0x0C9C, 0x0CAC, 0x0CBB,//
- 0x0CCA, 0x0CD9, 0x0CE8, 0x0CF7, 0x0D06, 0x0D14, 0x0D23, 0x0D31, 0x0D3F, 0x0D4D,//
- 0x0D5B, 0x0D69, 0x0D76, 0x0D84, 0x0D91, 0x0D9F, 0x0DAC, 0x0DB9, 0x0DC6, 0x0DD2,//
- 0x0DDF, 0x0DEB, 0x0DF8, 0x0E04, 0x0E10, 0x0E1C, 0x0E28, 0x0E33, 0x0E3F, 0x0E4A,//
- 0x0E55, 0x0E60, 0x0E6B, 0x0E76, 0x0E81, 0x0E8B, 0x0E96, 0x0EA0, 0x0EAA, 0x0EB4,//
- 0x0EBE, 0x0EC8, 0x0ED1, 0x0EDB, 0x0EE4, 0x0EED, 0x0EF6, 0x0EFF, 0x0F07, 0x0F10,//
- 0x0F18, 0x0F21, 0x0F29, 0x0F31, 0x0F39, 0x0F40, 0x0F48, 0x0F4F, 0x0F56, 0x0F5D,//
- 0x0F64, 0x0F6B, 0x0F72, 0x0F78, 0x0F7F, 0x0F85, 0x0F8B, 0x0F91, 0x0F96, 0x0F9C,//
- 0x0FA1, 0x0FA7, 0x0FAC, 0x0FB1, 0x0FB6, 0x0FBA, 0x0FBF, 0x0FC3, 0x0FC7, 0x0FCB,//
- 0x0FCF, 0x0FD3, 0x0FD7, 0x0FDA, 0x0FDE, 0x0FE1, 0x0FE4, 0x0FE7, 0x0FE9, 0x0FEC,//
- 0x0FEE, 0x0FF0, 0x0FF2, 0x0FF4, 0x0FF6, 0x0FF8, 0x0FF9, 0x0FFB, 0x0FFC, 0x0FFD,//
- 0x0FFE, 0x0FFE, 0x0FFF, 0x0FFF, 0x0FFF, 0x0FFF}; //
- /****************************************************
- Function name: Em_Sin
- description: calculate sin(theta)
- input: Angle(0x3FFFFF equal one Cycle
- output:
- ****************************************************/
- signed long Em_Sin(unsigned long Angle)
- {
- unsigned long AngleTemp;
- signed long SineValue;
- AngleTemp = Angle >> ;
- AngleTemp &= 0x03FF; //0~1024
- if (AngleTemp <= )
- {
- SineValue = SinTbl[AngleTemp];
- }
- else if (AngleTemp <= )
- {
- AngleTemp = - AngleTemp;
- SineValue = SinTbl[AngleTemp];
- }
- else if (AngleTemp <= )
- {
- AngleTemp -= ;
- SineValue = -SinTbl[AngleTemp];
- }
- else if (AngleTemp <= )
- {
- AngleTemp = - AngleTemp;
- SineValue = -SinTbl[AngleTemp];
- }
- return (SineValue);
- }
- //EmMath.h
- #ifndef __QM_MATH_H__
- #define __QM_MATH_H__
- #define PI 3.1415926
- signed long Em_Sin(unsigned long Angle);
- #endif
- %lct_trial.m
clc;- clear all;
- close all;
- bdclose all;
- %%
- lct_spec = legacy_code('initialize');
- lct_spec.SFunctionName = 'sfun_Em_Math';
- lct_spec.HeaderFiles = {'EmMath.h'};
- lct_spec.SourceFiles = {'EmMath.c'};
- % signed long Q12_Sin(unsigned long Angle)
- lct_spec.OutputFcnSpec = 'int32 y1 = Em_Sin(uint32 u1)';
- legacy_code('sfcn_cmex_generate', lct_spec);
- legacy_code('compile', lct_spec);
- legacy_code('slblock_generate', lct_spec, 'lct_model');
- %% struct model input
- stop_time = get_param(gcs, 'StopTime');
- simin.time = [0:str2num(stop_time)]';
- simin.signals.values = [0:length(simin.time) - 1]';
- simin.signals.demensions = [length(simin.time) 1];
- ### Start Compiling sfun_Em_Math
- mex('-IC:\Users\lenovo\Desktop', '-c', '-outdir', 'C:\Users\lenovo\AppData\Local\Temp\tp90d85757_f87e_4031_a3f5_a7e8c4e1b287', 'C:\Users\lenovo\Desktop\EmMath.c')
- 使用 'Microsoft Visual C++ 2010 (C)' 编译。
- MEX 已成功完成。
- ### Finish Compiling sfun_Em_Math
- ### Exit
- //sfun_Em_Math.c
- /**
- * sfun_Em_Math.c
- *
- * ABSTRACT:
- * The purpose of this sfunction is to call a simple legacy
- * function during simulation:
- *
- * int32 y1 = Em_Sin(uint32 u1)
- *
- * Simulink version : 9.1 (R2018a) 06-Feb-2018
- * C source code generated on : 04-Feb-2020 11:38:21
- *
- * THIS S-FUNCTION IS GENERATED BY THE LEGACY CODE TOOL AND MAY NOT WORK IF MODIFIED
- */
- /**
- %%%-MATLAB_Construction_Commands_Start
- def = legacy_code('initialize');
- def.SFunctionName = 'sfun_Em_Math';
- def.OutputFcnSpec = 'int32 y1 = Em_Sin(uint32 u1)';
- def.HeaderFiles = {'EmMath.h'};
- def.SourceFiles = {'EmMath.c'};
- legacy_code('sfcn_cmex_generate', def);
- legacy_code('compile', def);
- %%%-MATLAB_Construction_Commands_End
- */
- /* Must specify the S_FUNCTION_NAME as the name of the S-function */
- #define S_FUNCTION_NAME sfun_Em_Math
- #define S_FUNCTION_LEVEL 2
- /**
- * Need to include simstruc.h for the definition of the SimStruct and
- * its associated macro definitions.
- */
- #include "simstruc.h"
- /* Specific header file(s) required by the legacy code function */
- #include "EmMath.h"
- /* Function: mdlInitializeSizes ===========================================
- * Abstract:
- * The sizes information is used by Simulink to determine the S-function
- * block's characteristics (number of inputs, outputs, states, etc.).
- */
- static void mdlInitializeSizes(SimStruct *S)
- {
- /* Number of expected parameters */
- ssSetNumSFcnParams(S, );
- /* Set the number of work vectors */
- if (!ssSetNumDWork(S, )) return;
- ssSetNumPWork(S, );
- /* Set the number of input ports */
- if (!ssSetNumInputPorts(S, )) return;
- /* Configure the input port 1 */
- ssSetInputPortDataType(S, , SS_UINT32);
- {
- int_T u1Width = ;
- ssSetInputPortWidth(S, , u1Width);
- }
- ssSetInputPortComplexSignal(S, , COMPLEX_NO);
- ssSetInputPortDirectFeedThrough(S, , );
- ssSetInputPortAcceptExprInRTW(S, , );
- ssSetInputPortOverWritable(S, , );
- ssSetInputPortOptimOpts(S, , SS_REUSABLE_AND_LOCAL);
- ssSetInputPortRequiredContiguous(S, , );
- /* Set the number of output ports */
- if (!ssSetNumOutputPorts(S, )) return;
- /* Configure the output port 1 */
- ssSetOutputPortDataType(S, , SS_INT32);
- {
- int_T y1Width = ;
- ssSetOutputPortWidth(S, , y1Width);
- }
- ssSetOutputPortComplexSignal(S, , COMPLEX_NO);
- ssSetOutputPortOptimOpts(S, , SS_REUSABLE_AND_LOCAL);
- ssSetOutputPortOutputExprInRTW(S, , );
- /* Register reserved identifiers to avoid name conflict */
- if (ssRTWGenIsCodeGen(S) || ssGetSimMode(S)==SS_SIMMODE_EXTERNAL) {
- /* Register reserved identifier for */
- ssRegMdlInfo(S, "Em_Sin", MDL_INFO_ID_RESERVED, , , ssGetPath(S));
- } /* if */
- /* This S-function can be used in referenced model simulating in normal mode */
- ssSetModelReferenceNormalModeSupport(S, MDL_START_AND_MDL_PROCESS_PARAMS_OK);
- /* Set the number of sample time */
- ssSetNumSampleTimes(S, );
- /* Set the compliance with the SimState feature */
- ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);
- ssSetSupportedForRowMajorCodeGen(S, true);
- ssSetArrayLayoutForCodeGen(S, SS_COLUMN_MAJOR);
- /* Set the Simulink version this S-Function has been generated in */
- ssSetSimulinkVersionGeneratedIn(S, "9.1");
- /**
- * All options have the form SS_OPTION_<name> and are documented in
- * matlabroot/simulink/include/simstruc.h. The options should be
- * bitwise or'd together as in
- * ssSetOptions(S, (SS_OPTION_name1 | SS_OPTION_name2))
- */
- ssSetOptions(S,
- SS_OPTION_USE_TLC_WITH_ACCELERATOR |
- SS_OPTION_CAN_BE_CALLED_CONDITIONALLY |
- SS_OPTION_EXCEPTION_FREE_CODE |
- SS_OPTION_WORKS_WITH_CODE_REUSE |
- SS_OPTION_SFUNCTION_INLINED_FOR_RTW |
- SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME
- );
- }
- /* Function: mdlInitializeSampleTimes =====================================
- * Abstract:
- * This function is used to specify the sample time(s) for your
- * S-function. You must register the same number of sample times as
- * specified in ssSetNumSampleTimes.
- */
- static void mdlInitializeSampleTimes(SimStruct *S)
- {
- ssSetSampleTime(S, , INHERITED_SAMPLE_TIME);
- ssSetOffsetTime(S, , FIXED_IN_MINOR_STEP_OFFSET);
- #if defined(ssSetModelReferenceSampleTimeDefaultInheritance)
- ssSetModelReferenceSampleTimeDefaultInheritance(S);
- #endif
- }
- /* Function: mdlOutputs ===================================================
- * Abstract:
- * In this function, you compute the outputs of your S-function
- * block. Generally outputs are placed in the output vector(s),
- * ssGetOutputPortSignal.
- */
- static void mdlOutputs(SimStruct *S, int_T tid)
- {
- /* Get access to Parameter/Input/Output/DWork data */
- int32_T* y1 = (int32_T*) ssGetOutputPortSignal(S, );
- uint32_T* u1 = (uint32_T*) ssGetInputPortSignal(S, );
- /* Call the legacy code function */
- *y1 = Em_Sin(*u1);
- }
- /* Function: mdlTerminate =================================================
- * Abstract:
- * In this function, you should perform any actions that are necessary
- * at the termination of a simulation.
- */
- static void mdlTerminate(SimStruct *S)
- {
- }
- /* Required S-function trailer */
- #ifdef MATLAB_MEX_FILE
- # include "simulink.c"
- #else
- # include "cg_sfun.h"
- #endif
lct_model:
Simulink仿真入门到精通(十) S函数的更多相关文章
- Simulink仿真入门到精通(十九) 总结回顾&自我练习
从2019年12月27到2020年2月12日,学习了Simulink仿真及代码生成技术入门到精通,历时17天. 学习的比较粗糙,有一些地方还没理解透彻,全书梳理总结: Simulink的基础模块已基本 ...
- Simulink仿真入门到精通(八) M语言对Simulink模型的自动化操作及配置
8.1 M语言控制模型的仿真 M语言与Simulink结合的方式: 在Simulink模型或模块中使用回调函数 在M语言中调用与模型相关的命令,控制模型的建立,设置模块的属性,增删信号线,以及运行模型 ...
- Simulink仿真入门到精通(五) Simulink模型的仿真
5.1 模型的配置仿真 由各种模块所构建的可视化逻辑连接,只是模型的外在表现,模型仿真的核心驱动器是被称作解算器(Solver)的组件,相当于Simulink仿真过程的心脏,驱动着模型仿真,它在每一个 ...
- Simulink仿真入门到精通(三) Simulink信号
3.1 Simulink信号概述 所谓信号,表示一种随着时间而变化的量,在时间轴上的采样时刻都对应有数值. 信号在Simulink中是相当重要的组成部分,有线(line)表示,在模型中穿针引线地将各模 ...
- Simulink仿真入门到精通(二) Simulink模块
2.1 Simulink模块的组成要素 用户构建系统模型时无需直接面对成千上万行的代码,而是通过模块化图形界面以模块化的方式构建,能够使理解变得容易,让大脑减负.通过层次化模块分布将系统功能模块化,而 ...
- Simulink仿真入门到精通(十八) TLC语言
TLC(Target Language Compiler)是一种为转换为目标语言而存在的额解释性语言,其目的就是将模型中编译出来的rtw文件转换为目标代码(C/C++等).与M语言类似,既可以写成脚本 ...
- Simulink仿真入门到精通(十五) Simulink在流程工业中的仿真应用
15.1 工业乙醇生产与计算机仿真 乙醇作为可再生清洁能源不仅可以代替四乙基铅作为汽油的防爆剂,还可以制造汽油醇.这一巨大的潜在需求促使人们去寻找提高乙醇工业生产率的途径,使人们着手于发酵工程的研究. ...
- Simulink仿真入门到精通(十四) Simulink自定义环境
14.1 Simulink环境自定义功能 sl_sustomization.m函数是Simulink提供给用户使用MATLAB语言自定义Simulink标准人机界面的函数机制.若sl_sustomiz ...
- Simulink仿真入门到精通(七) Simulink的回调函数
7.1 什么是回调函数 Callback functions(回调函数)是因某种操作而除法对其调用的函数,如按下按钮或双击操作等. 常用的Simulink回调函数可应用在以下场合: 打开Simulin ...
随机推荐
- scala语言yield配合for的用法实例
yield配合for的用法 话不多说见实例 package com.donews.reynold /** * Created by reynold on 2017/3/23. */ object Sc ...
- deeplearning.ai 卷积神经网络 Week 1 卷积神经网络
1. 传统的边缘检测(比如Sobel)手工设计了3*3的filter(或者叫kernel)的9个权重,在深度学习中,这9个权重都是学习出来的参数,会比手工设计的filter更好,不但可以提取90度.0 ...
- mysql 事务处理 (转)
事务处理在各种管理系统中都有着广泛的应用,比如人员管理系统,很多同步数据库操作大都需要用到事务处理.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如 ...
- 林轩田机器学习基石笔记3—Types of Learning
上节课我们主要介绍了解决线性分类问题的一个简单的方法:PLA.PLA能够在平面中选择一条直线将样本数据完全正确分类.而对于线性不可分的情况,可以使用Pocket Algorithm来处理.本节课将主要 ...
- ionic2踩坑之文本域自适应高度(自定义指令,适用angular2)
话不多说,看代码: import { Directive, ElementRef, HostListener,Input, Renderer, Component } from '@angular/c ...
- jenkins使用(3)-设置定时任务
配置时间如果错误,代码不会运行 *表示任意时刻
- tomcat一闪而过
JAVA_HOME should point to a JDK not a JRE |vista tomcat 有的朋友在启动Tomcat的时候会出现问题. 1例如: 手动点击startup.bat ...
- Ionic3学习笔记(六)存储之使用 SQLite
本文为原创文章,转载请标明出处 目录 安装 CURD操作 1. 安装 命令行输入 ionic cordova plugin add cordova-sqlite-storage npm install ...
- MongoDB启动.mongorc.js报错解决方法
在bin目录下输入./mongo --norc 不去加载.mongorc.js
- MySQL5.6 数据库主从(Master/Slave)同步安装与配置详解
.安装环境 .基本环境配置 .Master的配置 .Slave的配置 .添加需要同步的从库Slave .真正的测试 安装环境 1 操作系统 :CentOS 6.5 2 数据库版本:MySQL 5.6. ...