Main Content

调用可重用的外部算法代码进行仿真和代码生成

代码重用可带来业务和技术上的优势。从业务角度来看,代码重用可节省时间和资源。从技术角度来看,代码重用可提高一致性,减少内存要求。其他考虑因素包括:

  • 模块化应用程序

  • 重用优化的算法

  • 与预定义数据集集成

  • 开发应用程序变体

以下各项为独立于硬件且可重用的算法代码,可考虑导入 Simulink® 环境中以进行仿真和代码生成:

  • 工具函数

  • 查找表

  • 数字滤波器

  • 专用积分器

  • 比例积分导数 (PID) 控制模块

工作流

要调用可重用的外部算法代码进行仿真和代码生成,请依次执行下表中列出的任务。

任务操作更多信息
1检查您对外部代码特性和集成要求的评估。

Choose an External Code Integration Workflow

2基于外部代码的编程语言,选择一种集成方法以将外部代码添加到 Simulink 模型中。

选择集成方法

3通过仿真模型验证算法行为和性能。

仿真

4为代码生成定义模型数据的表示。

代码接口配置Exchange Data Between External C/C++ Code and Simulink Model or Generated Code

5配置模型以进行代码生成。

模型配置集自定义

6生成代码和代码生成报告。

代码生成

7检查生成的代码接口和静态代码度量。

Analyze Generated Data Code Interface ReportAnalyze Generated Service Code Interface ReportStatic Code Metrics

8从模型中编译可执行程序。

在 Simulink 环境中编译集成的代码

9验证可执行程序的行为是否符合预期。

验证和测试验证、测试和认证

选择集成方法

有几种方法可以将可重用的算法代码集成到 Simulink 环境中进行代码生成。有些方法直接集成外部代码。其他方法先将外部代码转换为 Simulink 或 Stateflow® 建模元素用于仿真,随后从建立的模型设计进行代码生成。您选择的集成方法取决于:

  • 外部代码的编程语言 - MATLAB®、C、C++ 或 Fortran

  • 您的编程语言经验和偏好

  • 性能要求

  • 算法必须用于建立连续时间动态模型,还是将算法集成到使用离散和连续时间的应用程序中

  • 是否希望利用基于模型的设计

  • 所需的对代码生成器生成的代码的控制程度

要为可重用算法选择一种方法,请参阅与您的外部算法代码的编程语言相关的小节。

外部 MATLAB 代码的集成方法

有多种方法可以将外部 MATLAB 代码集成到 Simulink 环境中。下表可帮助您根据集成要求为应用程序选择最佳集成方法。

条件或要求操作更多信息
  • 外部代码支持 MATLAB 代码生成子集

  • 您要从 Simulink 模型中调用 MATLAB 代码

将 MATLAB Function 模块添加到模型中。在该模块中嵌入 MATLAB 代码。
  • 外部代码支持 MATLAB 代码生成子集

  • 您要从 Simulink 模型中调用 MATLAB 代码

  • 您的算法包括处理大量数据流的迭代计算

向模型中添加 MATLAB System 模块。将 MATLAB 代码作为 System object™ 嵌入该模块。
  • 外部代码支持 MATLAB 代码生成子集

  • 您要从 Simulink 模型中调用 MATLAB 代码

  • 您的算法包括基于状态机和流程图的设计逻辑

向模型中添加 Stateflow 图。使用 MATLAB 作为动作语言,从图中调用外部代码。
您想使用 parfor 函数进行并行计算或使用 MATLAB Coder™Simulink Coder 和 Embedded Coder® 可用的接口数据类型。要使用 parfor,必须安装 Parallel Computing Toolbox™。使用软件生成 C 代码。然后,以外部 C 代码形式调用生成的代码。
您拥有 C 或 C++ 编程经验,外部 MATLAB 代码非常简洁且主要使用 C 或 C++ 构造。手动将 MATLAB 代码转换为 C 或 C++ 代码。为 C 或 C++ 代码选择一种集成方法。

外部 C 或 C++ 代码的集成方法

外部 MATLAB 代码的有些部分可对应到内置模块。使用适用的内置模块在模型中开发算法。
算法必须用于建立连续状态动态模型。编写一个 MATLAB S-Function,并为生成代码编写对应的算法的 TLC 文件。将 S-Function 添加到您的模型中。

要将外部 MATLAB 代码嵌入 MATLAB Function 模块中或使用 MATLAB Coder 软件从 MATLAB 代码中生成 C 或 C++ 代码,MATLAB 代码必须使用 C/C++ 代码生成支持的函数和类。

外部 C 或 C++ 代码的集成方法

有多种方法可以将外部 C 或 C++ 代码集成到 Simulink 环境中。下表可帮助您根据集成要求为应用程序选择最佳集成方法。

条件或要求操作更多信息
您要将外部 C 代码与生成的 C++ 代码集成在一起,或者反之通过修改外部代码的语言以与生成代码的语言选择一致。修改外部代码的编程语言以匹配生成的代码
  • 已有对自定义功能建模的现有 C 代码。您要将代码集成到 Simulink 模块中。

  • 您的函数不读写全局/静态变量。

  • 您要轻松地与 Simulink Coverage™Simulink Test™Simulink Design Verifier™ 集成

对于用 C 语言编写的简单算法,考虑使用 Simulink C Caller 模块。

使用 C Caller 模块集成 C 代码
  • 已有对自定义功能建模的现有 C 代码。您要从一个 Simulink 模块中调用多个 C 函数,或有条件地调用 C 函数。

  • 您要在调用 C 函数之前和之后使用 C 代码来预处理和后处理数据。

  • 您要为仿真和代码生成指定不同代码。

为您的模型添加一个 C Function 模块。使用 MATLAB Function 模块集成 C 代码
  • 算法必须用于对离散和连续的状态动态建模以进行仿真和快速原型。

  • 外部代码需要定点接口。

  • 编程经验有限。您希望能够以基本的灵活性轻松控制代码生成器为快速原型生成的代码。

使用 S-Function Builder 生成 S-Function 和 TLC 文件。如有必要,手动细化生成的代码以满足应用程序要求。(如果您更改了生成的代码,则在您重新生成 S-Function 和 TLC 文件时,您将丢失这些更改。)
  • 您要对离散时间应用程序进行仿真和生成外部代码。优化生成的代码至关重要。

  • 您希望能够以适度的灵活性轻松控制代码生成器生成的代码。

  • 您有 C 或 C++ 编程经验,但您更喜欢生成用于将代码添加到模型中的文件。

使用代码继承工具生成 S-Function 和 TLC 文件。如有必要,手动细化生成的代码以满足应用程序要求。(如果您更改了生成的代码,则在您重新生成 S-Function 和 TLC 文件时,您将丢失这些更改。)

  • 应用程序需要的入口函数多于代码生成器通常生成的入口函数,例如,需要的入口函数不仅仅是 model_stepmodel_initializemodel_terminate 入口函数。

    您需要最大的灵活性来控制代码生成器生成的代码。

手动编写 S-Function 和 TLC 文件。
您的算法包括基于状态机和流程图的设计逻辑。或者,要集成的函数必须使用全局变量与模型交换数据。该函数定义全局变量,并使用它们来写函数的输出,而不是返回值(返回)或将输出写至参量。向模型中添加 Stateflow 图。使用 C 语言作为动作语言从图中调用外部代码。在图中,编写调用外部函数并读写全局变量的代码。要使用外部代码的输出来执行计算,模型必须在执行期间从全局变量中读取数据。将外部代码插入 Stateflow 图中
您要在 Stateflow 图中包含外部 C 或 C++ 代码,用于仿真和代码生成。配置包含图的模型以应用外部 C 或 C++ 代码。
您很快要在模型中嵌入对外部 C 或 C++ 代码的调用。性能不是问题。从 MATLAB Function 模块中调用具有 coder.ceval 函数的 C 或 C++ 代码。

修改外部代码的编程语言以匹配生成的代码

要将外部 C 代码与生成的 C++ 代码集成(或者反之),请修改外部代码的语言以与生成代码的编程语言选择一致。使编程语言匹配的选项包括:

  • 用生成代码的语言选择编写或重写外部代码。

  • 如果您正在生成 C++ 代码并且外部代码是 C 代码,则为每个 C 函数创建一个为该函数建立原型的头文件。使用以下格式:

    #ifdef __cplusplus
    extern "C" {
    #endif
    int my_c_function_wrapper();
    #ifdef __cplusplus
    }
    #endif

    原型充当函数包装器。如果您的编译器支持 C++ 代码,则会定义值 __cplusplus。链接设定 extern "C" 指定不带名称修饰的 C 链接。

  • 如果您正在生成 C 代码并且外部代码是 C++ 代码,请在每个 .cpp 文件中包含 extern "C" 链接设定。例如,以下示例展示文件 my_func.cpp 中的 C++ 代码:

    extern "C" {
    
    int my_cpp_function()
    {
      ...
    }
    }

外部 Fortran 代码的集成方法

要集成外部 Fortran 代码,请执行下列步骤:

  1. 编写一个 S-Function 和对应的 TLC 文件。

  2. 将 S-Function 添加到您的模型中。

  3. 如有必要,在 Simulink 环境中添加支持文件和控制模型代码生成与编译。

请参阅 C/C++ S-Function BasicsIntegrate Fortran Code into SimulinkS-Function 和代码生成Fortran S-Function Examples

将外部代码插入 Stateflow 图中

为库图集成外部代码

要集成仅应用于 Stateflow 库图的外部代码以进行代码生成,则对于为您的主模型提供了 Stateflow 图的每个库模型,请完成以下步骤。然后再生成代码。

  1. 在 Stateflow 编辑器中,打开“模型配置参数”对话框。选择参数使用本地自定义代码设置(不从主模型继承)

    库模型在代码生成过程中会保留它自己的自定义代码设置。

  2. 在子窗格中指定您的自定义代码。

    请遵循Specify Relative Paths to Custom Code (Stateflow) 中的规范。

    如果您为仿真指定了自定义代码设置,则可以将这些设置应用于代码生成。要避免两次输入相同的信息,请选择使用与仿真目标相同的自定义代码设置

  3. 点击确定

为每个库模型完成上述步骤后,生成代码。

为所有图集成外部代码

要集成应用于所有图的外部代码以进行代码生成,请执行以下操作:

  1. 为主模型的代码生成指定自定义代码选项。

    1. 在“模型配置参数”对话框中,选择代码生成 > 自定义代码

    2. 在自定义代码文本字段中,指定您的自定义代码。

      请遵循Specify Relative Paths to Custom Code (Stateflow) 中的规范。

      如果您为仿真指定了自定义代码设置,则可以将这些设置应用于代码生成。要避免两次输入相同的信息,请选择使用与仿真目标相同的自定义代码设置

  2. 为向主模型提供 Stateflow 图的每个库模型进行代码生成配置。在 Stateflow 编辑器中,打开“模型配置参数”对话框。清除参数使用本地自定义代码设置(不从主模型继承)。库图将继承主模型的自定义代码设置。点击确定

  3. 生成代码。

相关主题