S-Function和S-Function Builder使用(使用C/C++)

S-Function和S-Function Builder使用(使用C/C++)

1 两者的区别

S-FunctionS-Function Builder都是Simulink中用于自定义块的工具,但它们的使用方式和适用场景有所不同。以下是两者的主要区别:

1.1 S-Function

  • 定义:S-Function(系统功能块)是一种可以用C、C++、Fortran或MATLAB编写的自定义Simulink块。它提供了对Simulink建模环境的深度集成。
  • 灵活性:由于可以使用多种编程语言,S-Function具有高度的灵活性和可定制性。用户可以实现复杂的算法和数据处理。
  • 性能:通常,S-Function能够提供更高的性能,因为它们可以针对特定的应用进行优化。
  • 使用场景:适用于需要高度定制的应用,如实时系统、特定硬件接口或复杂的数学模型。
  • 开发过程:开发S-Function需要较好的编程知识,需要用户手动管理输入输出、参数设置等。

1.2 S-Function Builder

  • 定义:S-Function Builder是Simulink提供的一个图形化工具,允许用户通过图形界面生成S-Function,而无需手动编写底层代码。
  • 简易性:相较于手动编写S-Function,S-Function Builder使得创建自定义块更加简单和直观。用户只需通过图形界面定义输入、输出、参数以及算法。
  • 功能限制:虽然使用S-Function Builder可以快速生成S-Function,但对于复杂的功能,用户可能需要在生成的代码基础上进行手动修改。
  • 使用场景:适用于那些希望快速开发自定义块,但又不想深入底层代码的用户。
  • 开发过程:开发过程更为简单,用户可以在图形化界面中设置参数、输入输出、数据类型等。

总结

  • S-Function适合需要深度定制和优化的用户,具有更高的灵活性和性能,但开发复杂度较高。
  • S-Function Builder适合需要快速开发自定义功能的用户,通过图形化界面简化了开发过程,但可能不如手动编写S-Function灵活。

希望这些信息能帮助你更好地理解S-Function和S-Funct

2 S-Function Builder使用(使用C/C++,MATLAB需要配置C/C++编译器)

2.1 使用介绍

在这里插入图片描述

使用S-Function Builder实现两个uint8类型的数字u0和u1进行相加,并输出double类型的y0:

1. 加入S-Function Builder模块,模块位于Simulink Library Browser的User-Defined Functions
在这里插入图片描述

2. 设置S-Function Builder,其中图中红框1为设置输入输出和参数配置,红框2为设置代码的具体逻辑,system_Outputs_wrapper为代码实现部分,其中system_Outputs_wrapper为功能实现的具体逻辑,红框3主要是为了设置输入输出端口的配置和参数配置,红框4为设置界面,主要设置离散连续数据和采样模型等。其中Editor中的代码逻辑如下所示。
在这里插入图片描述

/* Includes_BEGIN */
#include <math.h>
/* Includes_END */

/* Externs_BEGIN */
/* extern double func(double a); */
/* Externs_END */

void add_Start_wrapper(void)
{
/* Start_BEGIN */
/*
 * Custom Start code goes here.
 */
 /* Start_END */
 }

void add_Outputs_wrapper(const uint8_T *u0,
                         const uint8_T *u1,
                         real_T *y0)
{
/* Output_BEGIN */
/* Output_BEGIN */
/* 将两个 uint8 数字相加,并将结果存储为 double 格式 */
    *y0 = (double)(*u0 + *u1);
/* Output_END */
/* Output_END */
}

void add_Terminate_wrapper(void)
{
/* Terminate_BEGIN */
/*

Custom Terminate code goes here.
*/
/* Terminate_END */
}

注:采样部分可以直接继承模块外的,即使用Inherited

3. 模块使用,首先要设置S-Function Name,之后点击Build按钮,Build按钮的作用是将你定义的 S-Function 代码编译并生成一个可用的S-Function模块(即 .mex 文件),显示S-function ‘你的S-function名称.mexw64’ created successfully,即代表S-function构建成功可以使用了

4.总结:S-Function Builder使用图形化界面可以设置输入和输入以及参数,只需要考虑具体逻辑,较为简单但是灵活性比较底。

3 S-Function使用(使用C/C++,MATLAB需要配置C/C++编译器)

C Mex S函数的优点:
——**运行速度和效率高。**使用C语言编写S函数成为C Mex S函数,相比于解释运行的M S函数,在仿真过程中不需要反复调用MATALB解释器,而是在运行前将.c文件编译成mexw32/mexw64类型的可执行文件,运行速度和效率上有明显优势;
——**灵活。**采用C语言拥有编程语言上的灵活性优势;
——C Mex S-function能够支持硬件外设驱动的自定义功能,可以构建自己的算法库和驱动块库。
——**资源重用。**可以直接使用已有C代码。
在这里插入图片描述

3.1 函数的构建与编译

C Mex S函数的执行方式如上图所示,一个C++的代码需要按照以上的格式进行,以下是使用C++代码实现两个uint8类型的数字u0和u1进行相加,并输出double类型的y0:

#define S_FUNCTION_LEVEL 2 // 宏定义了 S-函数的版本级别
#define S_FUNCTION_NAME  s_function_add // 定义了 S-函数的名称

#include "simstruc.h"
#include <stdio.h>  // 包含 printf 函数的头文件,主要进行打印查看

// Function: mdlInitializeSizes ===============================================
// 设置输入和输出的大小
static void mdlInitializeSizes(SimStruct *S)
{
    ssSetNumSFcnParams(S, 0); // 设置 S-函数的参数数量;为0则没有额外的参数

    // 设置两个输入端口
    if (!ssSetNumInputPorts(S, 2)) return; // 设置输入端口的数量为 2
    ssSetInputPortWidth(S, 0, 1); // 第一个输入端口宽度为 1
    ssSetInputPortWidth(S, 1, 1); // 第二个输入端口宽度为 1
    ssSetInputPortDataType(S, 0, SS_UINT8); // 设置第一个输入数据类型为 uint8
    ssSetInputPortDataType(S, 1, SS_UINT8); // 设置第二个输入数据类型为 uint8
    ssSetInputPortDirectFeedThrough(S, 0, 1); // 输入数据直接传递到输出
    ssSetInputPortDirectFeedThrough(S, 1, 1); // 输入数据直接传递到输出
    
    // 设置一个输出端口
    if (!ssSetNumOutputPorts(S, 1)) return; // 设置输出端口的数量
    ssSetOutputPortWidth(S, 0, 1); // 输出端口宽度为 1
    ssSetOutputPortDataType(S, 0, SS_DOUBLE); // 设置输出数据类型为 double
    
    ssSetNumSampleTimes(S, 1); // 一个采样时间
}

// Function: mdlInitializeSampleTimes =========================================
// 设置采样时间
static void mdlInitializeSampleTimes(SimStruct *S)
{
    ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME); // 设置 S-函数的采样时间
    ssSetOffsetTime(S, 0, 0.0); // 设置 S-函数的偏移时间
}

// Function: mdlOutputs =======================================================
// 计算输出
static void mdlOutputs(SimStruct *S, int_T tid)
{
    // 获取两个输入信号
    InputUInt8PtrsType u0 = (InputUInt8PtrsType)ssGetInputPortSignalPtrs(S, 0); // 获取第一个输入信号
    InputUInt8PtrsType u1 = (InputUInt8PtrsType)ssGetInputPortSignalPtrs(S, 1); // 获取第二个输入信号
    
    // 获取输出信号
    real_T *y = ssGetOutputPortRealSignal(S, 0);
    
    // 将两个 uint8 的输入值相加,并将结果存储为 double
    uint8_T input1 = *u0[0];
    uint8_T input2 = *u1[0];
    
    double result = (double)(input1 + input2);
    
    // 打印输入和输出值
    printf("Input 1 value: %u\n", input1);
    printf("Input 2 value: %u\n", input2);
    printf("Output value (sum): %f\n", result);
    
    // 将结果赋值给输出
    y[0] = result;
}

// Function: mdlTerminate =====================================================
// 清理工作
static void mdlTerminate(SimStruct *S)
{
    // 在这里进行任何清理工作(如动态分配的内存)
}

/*=============================*

Required S-function trailer *
*=============================*/
#ifdef  MATLAB_MEX_FILE
#include "simulink.c"
#else
#include "cg_sfun.h"
#endif

其中mdlInitializeSizes函数主要定义输入和输入设置,mdlInitializeSampleTimes主要设置采样部分,mdlOutputs主要是计算模块的输出,mdlTerminate主要进行清理工作。S_FUNCTION_NAME这个宏主要是定义函数的名称。

编译型语言编写的程序执行之前,需要一个专门的编译过程,把程序编译成为机器语言的文件,如exe文件或mexw32/menw64文件,运行时不需要重新翻译。

在 MATLAB 中使用 mex 命令编译 C/C++ 代码生成 MEX 文件(MATLAB 可执行文件),用于加速函数或实现自定义功能,编译后会生成mexw64文件。

mex s_function_add.cpp

3.1 函数的使用

1.加入S-Function模块,模块位于Simulink Library Browser的User-Defined Functions
在这里插入图片描述

2.在Block Parameters:S-Function的S-function name中将编译好的mex文件名填写上去,点击Apply即可应用。

在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值