主要内容

使用构型

Ifelseifelse 构造的 Simulink 构型

应对 ifelseifelse 构造使用下面这些构型。

功能Simulink 构型

使用 Switch 模块时的 ifelseifelse 构造。

if (If_Condition)
{
	output_signal = If_Value;
}
else if (Else_If_Condition)
{
	output_signal = Else_If_Value;
}
else
{
	output_signal = Else_Value;
}

使用动作子系统时的 ifelseifelse 构造

if (Fault_1_Active & Fault_2_Active)
{
	ErrMsg = SaftyCrit;
}
else if (Fault_1_Active | Fault_2_Active)
{
	ErrMsg = DriverWarn;
}
else
{
	ErrMsg = NoFaults;

case 构造的 Simulink 构型

应对 case 构造使用下面这些构型。

功能Simulink 构型

使用动作子系统的 case 构造。

switch (PRNDL_Enum)
{
	case 1
		TqEstimate = ParkV;
		break;
	case 2
		TqEstimate = RevV;	
		break;
	default 
		TqEstimate = NeutralV;
		break;
}

使用 Multiport Switch 模块的 case 构造。

switch (Selection)
{
	case 1:
		output_signal =
			look1_binlxpw(In2,y1,x1,3U);
		break;
	case 2:
		output_signal =
			look1_binlxpw(In3,y2,x2,3U);
		break;
	case 3:
		output_signal =
			look1_binlxpw(In4,y3,x3,3U);
		break;
	default:
		output_signal =
			look1_binlxpw(In5,y4,x4,3U);
		break;
}

逻辑构造的 Simulink 构型

应对逻辑构造使用下面这些构型。

合取范式

析取范式

矢量信号的 Simulink 构型

应对矢量信号使用下面这些构型。

功能Simulink 构型

矢量信号与参数(标量)乘法

for (i=0; i>input_vector_size; i++) {
	output_vector[i] = input_vector[i] *
		tunable_parameter_value;
}

(参考:使用 R2013b 生成的代码)

for (i = 0; i < input_vectorDim; i++) {
	output_vector[i] =
		tunable_parameter_value *
		input_vector[i];
} 

(由于代码是使用可变数量的维度生成的,因此普通循环的上限是直接值。)

矢量信号与参数(矢量)的乘法

for (i=0; i>input_vector_size; i++) {
	output_vector[i] = input_vector[i] *
		tunable_parameter_vector[i];
}

矢量信号元素乘法

output_signal = 1;
for (i=0; i>input_vector_size; i++) {
	output_signal = output_signal *
		input_vector[i];
}

矢量信号元素除法

output_signal = 1;
for (i=0; i>input_vector_size; i++) {
	output_signal = output_signal /
		input_vector[i];
}

矢量信号与参数(标量)加法

for (i=0; i>input_vector_size; i++) {
	output_vector[i] = input_vector[i] +
		tunable_parameter_value;
}

矢量信号与参数(矢量)加法

Vector signal and parameter (vector) addition

for (i=0; i>input_vector_size; i++) {
	output_vector[i] = input_vector[i] +
		tunable_parameter_vector[i];
}

矢量信号元素减法

output_signal = 0;
for (i=0; i>input_vector_size; i++) {
	output_signal = output_signal -
		input_vector[i]; 
}

保留最小值/最大值

使用 Switch 和 IfElseifElse 动作子系统

当相关的 elseifelse 操作仅涉及常量值的分配时,应使用 Switch 模块来对简单的 ifelseifelse 结构进行建模。

示例 - 推荐

对于简单的 ifelseifelse 结构,使用 Switch 模块。

示例 - 不推荐

使用 IfIf Action Subsystem 模块来实现简单的 ifelseifelse 结构。

示例 - 推荐

对于复杂的 ifelseifelse 结构,使用 IfIf Action Subsystem模块。

示例 - 不推荐

使用 Switch 模块来实现复杂的 ifelseifelse 结构。

使用 IfElseifElse 动作子系统替换多个开关

应避免频繁使用 Switch 模块进行条件分叉。而应使用目标上限(例如最多三级)。当超过目标值时,应使用基于 ifelseifelse 动作子系统的条件控制流。

示例 - 不推荐

四层嵌套。

示例 - 推荐

通过将第四层设置为一个 if 动作子系统,嵌套被限制为单层。

示例 - 不推荐

没有使用 if 动作子系统进行划分。

当应用 C 代码限制时,使用原子子系统 + 函数设置。这种情况下不需要使用 ifelseifelse 动作子系统了,而是可以将 Switch 模块的配置拆分并封装到子系统中。

五层嵌套模型示例 - 不推荐

五层嵌套模型示例 - 推荐

使用了一种描述方法,避免了在 Switch 模块中的分层嵌套。

虽然作为示例提供,但 if 动作子系统通常不用于切换固定值。在这些推荐和不推荐的示例中,如果用户不添加函数转换设置,则生成的 C 代码将是相同的。(在 R2010b 至 R2013a 中确认)C 代码不受约束。

使用条件控制流时动作子系统的使用规则

示例 - 推荐

当相关动作没有状态变量时,不应使用 if 动作子系统。

示例 - 推荐

使用五层嵌套的模型示例。由于没有内部状态,因此不会使用子系统进行分层。

示例 - 推荐

使用原子子系统来分割 Switch 模块的两侧,而无需使用动作子系统。

示例 - 不推荐

通过使用不必要的动作子系统进行分层。

如果某个功能可以通过动作子系统实现,则不必再使用动作子系统执行进一步分层。

在“不推荐”的例子中,在初始化第三层最低级别的 Unit Delay 模块时,首先在上面的第一层执行一次条件子系统初始化,然后在第二层再次执行一次,共计两次初始值设置。为了防止生成不必要的代码,建议不要在状态变量不存在的层级的条件子系统中进行列出或声明。

这基于这样的概念:通过降低层级来减少模型的复杂度。该规则的目的是避免执行不必要的初始化。

对于分岔条件嵌套结构较深的系统分岔,采用函数转换进行拆分,以减少代码分岔嵌套。将 Switch 模块前后的功能划分为各自的子系统,并将功能设置应用于原子子系统+功能。需要注意的是,这可能会导致意外的实现和不必要的 RAM 要求。

测试错误信息

当 Stateflow®(图形函数、MATLAB® 函数等)中使用的函数出现错误时,应将错误信息转化为便于测试的模型结构。

不检查函数返回的错误信息可能会导致意外行为。

示例 - 推荐

错误信息被并入模型结构,允许用户审查并对错误做出响应。

示例 - 不推荐

错误信息未并入模型结构。

条件的流程图构型

应对 Stateflow 流程图中的条件使用下面这些构型。

功能流程图构型

一个条件。

[condition]

最多三个条件,简短形式。

(这种形式不允许使用不同的逻辑运算符。请改用子条件。)

[condition1 && condition2 && condition3] 
 [condition1 || condition2 || condition3]

两个或更多条件,多行形式。

(这种形式不允许使用不同的逻辑运算符。请改用子条件。)

[condition1 ...
&& condition2 ... 
&& condition3] 
[condition1 ...
|| condition2 ...
|| condition3]

带子条件的条件。

(不允许使用不同的逻辑运算符连接子条件。必须使用括号。)

[(condition1a || condition1b) ... 
&& (condition2a || condition2b) ... 
&& (condition3)] 
[(condition1a && condition1b) ... 
|| (condition2a && condition2b) ... 
|| (condition3)]

视觉上分隔的条件

(这种形式可与前面的构型结合使用)

[condition1 && condition2] 
[condition1 || condition2]

条件动作的流程图构型

应对 Stateflow 流程图中的条件动作使用下面这些构型:

功能流程图构型

一个条件动作。

action;

两个或更多条件动作,多行形式。

(不允许在一行中包含两个或更多条件动作)

action1; ... 
action2; ... 
action3; ... 

视觉上分隔的条件动作

(这种形式可与前面的构型结合使用)

action1a; 
action1b; 
action2; 
action3;

IfElseifElse 构造的流程图构型

应对 Stateflow 流程图内的If 构造使用下面这些构型。

功能流程图构型

If 构造

if (condition){
	action;
}

Ifelse 构造

if (condition) {
	action1; 
}
else {
	action2; 
}

Ifelseifelse 构造

if (condition1) {
	action1;
}
else if (condition2) {
	action2; 
}
else if (condition3) {
	action3;
}
else {
	action4;
}

级联 if 构造。

if (condition1) {
	action1;
	if (condition2) {
		action2;
		if (condition3) {
			action3;
		}
	} 
}

case 构造的流程图构型

应对 Stateflow 流程图中的 case 构造使用下面这些构型。

功能流程图构型

具有排他选择的 case 构造。

selection = u1;
switch (selection) {
	case 1: 
		y1 = 1; 
		break;
	case 2:
		y1 = 2;
		break;
	case 3:
		y1 = 4;
		break;
	default: 
		y1 = 8;
}

具有排他条件的 case 构造。

c1 = u1;
c2 = u2;
c3 = u3;
if (c1 && ! c2 && ! c3) {
	y1 = 1;
}
elseif (! c1 && c2 && ! c3) {
	y1 = 2;
}
elseif (! c1 && ! c2 && c3) {
	y1 = 4;
}
else {
	y1 = 8;
}

循环构造的流程图构型

应使用下面这些构型在 Stateflow 流程图中创建循环构造。

功能流程图构型

For 循环构造

for ( index = 0;
			index < number_of_loops;
			index++ )
{
	action;
}

While 循环构造

while ( condition )
{
	action;
}

Do While 循环构造

do
{
	action;
}
while ( condition )

条件的状态机构型

应对 Stateflow 状态机中的条件使用下面这些构型

功能状态机构型

一个条件

(condition)

最多三个条件,简短形式

(这种形式不允许使用不同的逻辑运算符,而应使用子条件)

(condition1 && condition2) 
(condition1 || condition2)

两个或更多条件,多行形式

子条件是一组逻辑运算,全部属于同一类型,用括号括起来。

(这种形式不允许使用不同的运算符,而应使用子条件。)

(condition1 ... 
&& condition2 ... 
&& condition3) 

(condition1 ...
|| condition2 ...
|| condition3)

转移动作的状态机构型

应对 Stateflow 状态机中的转移动作使用下面这些构型。

功能状态机构型

一个转移动作。

action;

两个或更多转移动作,多行形式

(一行中不允许出现两个或更多转移动作。)

action1; 
action2; 
action3;

jc_0321 限制状态分层

在单个查看器(子查看器)内,应通过定义单个视图(子视图)的约束来限制多层分层。当超出定义的约束目标时,应使用子图来切换屏幕。

示例 - 推荐

第四层封装在子图中。

示例 - 不推荐

约束目标设置为三层,但是 Level_4_a 和 Level_4_b 的层级超过三层,而且是嵌套的。

每个 Stateflow 容器的状态数

每个 Stateflow 容器的状态数应由图中可查看的状态数决定。所有状态都应该可见且可读。

Stateflow 调用函数

如果调用目标的 Function-Call Subsystem 中存在一个状态,并且当调用方的状态变为非活动状态时需要“重置”该状态,则调用方应使用绑定操作。

Stateflow 中可用的函数类型

Stateflow 中使用的函数类型应取决于所需的处理。

对于图形函数,使用:

  • Ifelseifelse 逻辑

对于 Simulink® 函数,使用:

  • 传递函数

  • 积分器

  • 表查找

对于 MATLAB 函数,使用:

  • 复杂方程

  • Ifelseifelse 逻辑