在 C 语言状态图中调用 C 库函数
Simulink® 模型中的 Stateflow® 图具有一个动作语言属性,该属性定义状态和转移动作的语法。图的画布左下角的图标表示该图的动作语言。
MATLAB® 作为动作语言。
C 语言作为动作语言。
调用 C 库函数
您可以调用 C 数学库函数的以下子集:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Stateflow | |||||
** 您也可以将对 C 数学库的调用替换为该函数子集的应用程序特定实现。有关详细信息,请参阅用应用程序实现替换数学库函数。 |
当您调用这些函数时,除非所有输入参数都显式设置为单精度,否则应用双精度。当发生类型不匹配时,会将输入参数强制转换为预期类型以替换原始参数。例如,如果使用整数参数调用 sin
函数,则将输入参数强制转换为类型 double
的浮点数以替换原始参数。
注意
由于 C 库函数的输入参数首先转换为浮点数,因此具有类型为 int64
或 uint64
的参数的函数调用会导致精度损失。
如果您调用上面未列出的其他 C 库函数,请打开“配置参数”对话框,并在仿真目标窗格中输入适当的 #include
语句,如 Configure Custom Code for Your Model 中所述。
调用 abs 函数
对 Stateflow abs
函数的解释超出了标准 C 版本,包含所有类型的整数和浮点参数,如下所示:
如果
x
是int32
或int64
类型的整数,则标准 C 函数abs
应用于x
,即abs(x)
。如果
x
是int16
或int8
类型的整数,则将标准 Cabs
函数应用于转换为int32
类型整数的x
,即abs((int32)x)
。如果
x
是double
类型的浮点数,则将标准 C 函数fabs
应用于x
,即fabs(x)
。如果
x
是single
类型的浮点数,则将标准 C 函数fabs
应用于转换为double
类型的浮点数x
,即fabs((double)x)
。如果
x
是定点数,则将标准 C 函数fabs
应用于转换为double
类型的定点数,即fabs((double) Vx)
,其中 Vx
是x
的实际值。
如果您要使用严格意义上的标准 C abs
函数,则将其参数或返回值转换为整数类型。请参阅Type Cast Operations。
注意
如果您在自定义代码中声明 x
,则在所有情况下都将应用标准 C abs
函数。有关将自定义代码插入图中的说明,请参阅Reuse Custom Code in Stateflow Charts。
调用 min 和 max 函数
您可以通过在生成的代码顶部自动发出以下宏来调用 min
和 max
。
#define min(x1,x2) ((x1) > (x2) ? (x2):(x1)) #define max(x1,x2) ((x1) > (x2) ? (x1):(x2))
为了与名为 min()
或 max()
的用户图形函数保持兼容性,生成的代码使用以下格式的改造名称:<prefix>_min
。但是,如果将 min()
或 max()
图形函数导出到模型中的其他图,则这些函数的名称将不再以生成的代码中的改造名称发出,因而会发生冲突。为避免这种冲突,请重命名 min()
和 max()
图形函数。
用应用程序实现替换数学库函数
您可以对代码生成器进行配置,以更改它为数学库函数生成的代码,使之符合应用程序的要求。要执行此操作,请将代码生成器配置为在代码生成期间应用代码替换库 (CRL)。如果您有 Embedded Coder® 许可证,则可以开发并应用自定义代码替换库。
有关使用 MathWorks® 提供的代码替换库替换代码的详细信息,请参阅什么是代码替换? (Simulink Coder)和代码替换库 (Simulink Coder)。有关开发自定义代码替换库的信息,请参阅What Is Code Replacement Customization? (Embedded Coder)和Code You Can Replace From Simulink Models (Embedded Coder)。
调用自定义 C 代码函数
您可以指定用于 C 语言状态图的自定义代码函数以进行仿真和 C 代码生成。有关详细信息,请参阅Configure Custom Code for Your Model。
在图中调用自定义 C 函数的指导原则
使用名称、任意参数(置于括号内)以及分号(可选)来定义函数。
使用单引号将参数传递给用户编写的函数。例如
func('string')
。一个动作中可以嵌套多个函数调用。
动作可以调用返回标量值的函数(对于 MATLAB 函数,为
double
类型;对于用户编写的 C 函数,为任何类型)。
编写访问输入向量的自定义 C 函数的指导原则
使用
sizeof
函数来确定输入向量的长度。例如,您的自定义函数可以包含使用
sizeof
的 for 循环,如下所示:for(i=0; i < sizeof(input); i++) { ...... }
如果您的自定义函数多次使用输入向量长度的值,请在函数中包含指定输入向量长度的输入参数。
例如,您可以使用
input_length
作为sum
函数的第二个输入,如下所示:int sum(double *input, double input_length)
您的
sum
函数可以包含 for 循环,该循环将遍历输入向量的所有元素:for(i=0; i < input_length; i++) { ...... }
转移动作中的函数调用
下图显示了使用转移动作表示法的函数调用的示例格式。
如果以下条件成立,则使用 arg1
、arg2
和 arg3
对 fcn1
进行函数调用:
S1
被激活。发生事件
e
。条件
c
为 true。转移目标
S2
有效。
从 S2
到 S3
的转移中的转移动作显示了嵌套在另一个函数调用中的函数调用。
状态动作中的函数调用
下图显示了使用状态动作表示法的函数调用的示例格式。
该图的执行过程如下所示:
当到
S1
的默认转移发生时,S1
被激活。执行
entry
动作,使用指定参数对fcn1
进行函数调用。在仿真时间经过 5 秒后,
S1
变为非激活,S2
被激活。执行
during
动作,使用指定参数对fcn2
进行函数调用。在仿真时间经过 10 秒后,
S2
变为非激活,S1
再次被激活。在仿真结束之前,重复步骤 2 到 5。
按引用传递参数
Stateflow 动作可以按引用(而不是按值)将参数传递给用户编写的函数。特别是,动作可以传递指向值的指针而不是值本身。例如,动作可能包含以下调用:
f(&x);
其中 f
是自定义代码 C 函数,它需要指向 x
的指针作为参数。
如果 x
是在 Stateflow 层次结构中定义的数据项的名称,则适用以下规则:
不要使用指针传递从 Simulink 模型输入的数据项。
如果您需要按引用传递某输入项(例如数组),请将该项分配给一个局部数据项并按引用传递该局部数据项。
如果
x
的数据类型为boolean
,则您必须关闭代码生成器选项 使用位集来存储状态配置。如果
x
是数组且其第一个索引属性设置为 0(请参阅设置数据属性),则必须按如下所示调用函数。f(&(x[0]));
这会将
x
的第一个元素的指针传递给函数。如果
x
是数组且其第一个索引属性设置为非零数字(例如 1),则必须按以下方式调用函数:f(&(x[1]))
;这会将
x
的第一个元素的指针传递给函数。