开箱报告,Simulink Toolbox库模块使用指南(七)——S-Fuction Builder模块

本文主要是介绍开箱报告,Simulink Toolbox库模块使用指南(七)——S-Fuction Builder模块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

前言

S-Fuction Builder

模块配置

编写Update_wrapper()

编写Outputs_wrapper()

Build S-Fuction

仿真验证

生成代码

Tips

分析和应用

总结


前言

        见《开箱报告,Simulink Toolbox库模块使用指南(一)——powergui模块》

        见《开箱报告,Simulink Toolbox库模块使用指南(二)——MATLAB Fuction模块》

        见《开箱报告,Simulink Toolbox库模块使用指南(三)——Simscape 电路仿真模块》

        见《开箱报告,Simulink Toolbox库模块使用指南(四)——S-Fuction模块》

        见《开箱报告,Simulink Toolbox库模块使用指南(五)——S-Fuction模块(C MEX S-Function)》

        见《开箱报告,Simulink Toolbox库模块使用指南(六)——S-Fuction模块(TLC)》

S-Fuction Builder

        S-Fuction Builter模块Mathworks官方Help对该部分内容的说明如下所示。

        DFT算法的原理讲解和模块开发在前几篇文章中已经完成了,本文介绍如何使用S-Fuction Builter模块一步到位地自动开发DFT算法模块,包括建立C MEX S-Function文件、TLC文件和编译生成等工作。

模块配置

        第一步是模块配置,包括S-Fuction的名字、开发语言、输入输出端口、状态变量和固定参数等,如下图所示:

编写Update_wrapper()

         第二步是编写Update_wrapper()函数,沿用前期C MEX S-Function的代码,使用自动生成的函数接口,写出的Update_wrapper()函数如下:

void DFT_CMexSfuncBuilder_Update_wrapper(const real_T *u0,real_T *y0,real_T *xD,const real_T *Freq, const int_T p_width0)
{
/* Update_BEGIN */static real_T Fs = 10e3;static real_T L = 5e3;real_T Sr_cos;real_T Sr_sin;real_T T;if(xD[0]<=L){   Sr_cos = cos(2*3.14*xD[4]*xD[1]);Sr_sin = sin(2*3.14*xD[4]*xD[1]);xD[2] = xD[2] + u0[0]*Sr_cos;xD[3] = xD[3] + u0[0]*Sr_sin;xD[0] = xD[0] + 1;T = 1/Fs;xD[1] = xD[1] + T;}
/* Update_END */
}

编写Outputs_wrapper()

        第三步是编写Outputs_wrapper()函数,沿用前期C MEX S-Function的代码,使用自动生成的函数接口,写出的Outputs_wrapper()函数如下:

void DFT_CMexSfuncBuilder_Outputs_wrapper(const real_T *u0,real_T *y0,const real_T *xD,const real_T *Freq, const int_T p_width0)
{
/* Output_BEGIN */
/* This sample sets the output equal to the inputy0[0] = u0[0]; For complex signals use: y0[0].re = u0[0].re; y0[0].im = u0[0].im;y1[0].re = u1[0].re;y1[0].im = u1[0].im;*/static real_T L = 5e3;real_T real = 0;real_T imag = 0;real_T modl = 0;if(xD[0]==L+1){real = xD[2]/L*2;imag = xD[3]/L*2;modl = sqrt(real*real + imag*imag);y0[0] = modl;       }
/* Output_END */
}

Build S-Fuction

        上述配置和函数编写完成后,点击Build按钮,可以看到如下是信息:

        其中,DFT_CMexSfuncBuilder.c文件就是自动生成的C MEX文件,DFT_CMexSfuncBuilder_wrapper.c文件是C MEX文件中调用的wrapper函数,DFT_CMexSfuncBuilder.tlc是自动生成的TLC文件。

        与此同时,工程文件夹里边还会自动生成DFT_CMexSfuncBuilder.mexw64、rtwmakecfg.m和SFB__DFT_CMexSfuncBuilder__SFB.mat,都是S-Fuction的执行文件和代码生成和编译的相关文件。

仿真验证

        将上述编写好的S-Fuction Buider模块,放入Simulink模型中进行验证,如下所示:

        运行上述模型,得到的电流和电压如上图所示,与前期C MEX S-Function的结果一致。

        至此,可以证明该S-Fuction Buider模块可以较好地实现,手动开发C MEX S-Function相同的功能。

生成代码

        点击代码生成按钮,可以看到如下过程提示:

        点击打开报告按钮,可以看到如下生成报告:

        点击左侧的sfucbuilder.c超链接,可以看到如下生成的代码,其中30行到117行是该模型主要功能的代码,47行到86行是与我们S-Fuction Buider模块直接相关的代码。

File: sfucbuilder.c
1	/*
2	 * sfucbuilder.c
3	 *
4	 * Code generation for model "sfucbuilder".
5	 *
6	 * Model version              : 1.52
7	 * Simulink Coder version : 9.4 (R2020b) 29-Jul-2020
8	 * C source code generated on : Thu Oct  5 22:12:11 2023
9	 *
10	 * Target selection: grt.tlc
11	 * Note: GRT includes extra infrastructure and instrumentation for prototyping
12	 * Embedded hardware selection: Intel->x86-64 (Windows64)
13	 * Code generation objectives: Unspecified
14	 * Validation result: Not run
15	 */
16	
17	#include "sfucbuilder.h"
18	#include "sfucbuilder_private.h"
19	
20	/* Block signals (default storage) */
21	B_sfucbuilder_T sfucbuilder_B;
22	
23	/* Block states (default storage) */
24	DW_sfucbuilder_T sfucbuilder_DW;
25	
26	/* Real-time model */
27	static RT_MODEL_sfucbuilder_T sfucbuilder_M_;
28	RT_MODEL_sfucbuilder_T *const sfucbuilder_M = &sfucbuilder_M_;
29	
30	/* Model step function */
31	void sfucbuilder_step(void)
32	{
33	  /* Selector: '<Root>/Selector5' incorporates:
34	   *  Constant: '<Root>/Constant6'
35	   *  UnitDelay: '<S1>/Output'
36	   */
37	  sfucbuilder_B.Selector5 =
38	    sfucbuilder_ConstP.Constant6_Value[sfucbuilder_DW.Output_DSTATE];
39	
40	  /* Selector: '<Root>/Selector4' incorporates:
41	   *  Constant: '<Root>/Constant5'
42	   *  UnitDelay: '<S1>/Output'
43	   */
44	  sfucbuilder_B.Selector4 =
45	    sfucbuilder_ConstP.Constant5_Value[sfucbuilder_DW.Output_DSTATE];
46	
47	  /* S-Function (DFT_CMexSfuncBuilder): '<Root>/S-Function Builder' */
48	  DFT_CMexSfuncBuilder_Outputs_wrapper(&sfucbuilder_B.Selector4,
49	    &sfucbuilder_B.SFunctionBuilder, &sfucbuilder_DW.SFunctionBuilder_DSTATE[0],
50	    &sfucbuilder_ConstP.pooled1, 1);
51	
52	  /* S-Function (DFT_CMexSfuncBuilder): '<Root>/S-Function Builder1' */
53	  DFT_CMexSfuncBuilder_Outputs_wrapper(&sfucbuilder_B.Selector5,
54	    &sfucbuilder_B.SFunctionBuilder1, &sfucbuilder_DW.SFunctionBuilder1_DSTATE[0],
55	    &sfucbuilder_ConstP.pooled1, 1);
56	
57	  /* Switch: '<S3>/FixPt Switch' incorporates:
58	   *  Constant: '<S2>/FixPt Constant'
59	   *  Sum: '<S2>/FixPt Sum1'
60	   *  UnitDelay: '<S1>/Output'
61	   */
62	  if ((uint16_T)(sfucbuilder_DW.Output_DSTATE + 1U) > 4999) {
63	    /* Update for UnitDelay: '<S1>/Output' incorporates:
64	     *  Constant: '<S3>/Constant'
65	     */
66	    sfucbuilder_DW.Output_DSTATE = 0U;
67	  } else {
68	    /* Update for UnitDelay: '<S1>/Output' */
69	    sfucbuilder_DW.Output_DSTATE++;
70	  }
71	
72	  /* End of Switch: '<S3>/FixPt Switch' */
73	
74	  /* Update for S-Function (DFT_CMexSfuncBuilder): '<Root>/S-Function Builder' */
75	
76	  /* S-Function "DFT_CMexSfuncBuilder_wrapper" Block: <Root>/S-Function Builder */
77	  DFT_CMexSfuncBuilder_Update_wrapper(&sfucbuilder_B.Selector4,
78	    &sfucbuilder_B.SFunctionBuilder, &sfucbuilder_DW.SFunctionBuilder_DSTATE[0],
79	    &sfucbuilder_ConstP.pooled1, 1);
80	
81	  /* Update for S-Function (DFT_CMexSfuncBuilder): '<Root>/S-Function Builder1' */
82	
83	  /* S-Function "DFT_CMexSfuncBuilder_wrapper" Block: <Root>/S-Function Builder1 */
84	  DFT_CMexSfuncBuilder_Update_wrapper(&sfucbuilder_B.Selector5,
85	    &sfucbuilder_B.SFunctionBuilder1, &sfucbuilder_DW.SFunctionBuilder1_DSTATE[0],
86	    &sfucbuilder_ConstP.pooled1, 1);
87	
88	  /* Matfile logging */
89	  rt_UpdateTXYLogVars(sfucbuilder_M->rtwLogInfo,
90	                      (&sfucbuilder_M->Timing.taskTime0));
91	
92	  /* signal main to stop simulation */
93	  {                                    /* Sample time: [0.001s, 0.0s] */
94	    if ((rtmGetTFinal(sfucbuilder_M)!=-1) &&
95	        !((rtmGetTFinal(sfucbuilder_M)-sfucbuilder_M->Timing.taskTime0) >
96	          sfucbuilder_M->Timing.taskTime0 * (DBL_EPSILON))) {
97	      rtmSetErrorStatus(sfucbuilder_M, "Simulation finished");
98	    }
99	  }
100	
101	  /* Update absolute time for base rate */
102	  /* The "clockTick0" counts the number of times the code of this task has
103	   * been executed. The absolute time is the multiplication of "clockTick0"
104	   * and "Timing.stepSize0". Size of "clockTick0" ensures timer will not
105	   * overflow during the application lifespan selected.
106	   * Timer of this task consists of two 32 bit unsigned integers.
107	   * The two integers represent the low bits Timing.clockTick0 and the high bits
108	   * Timing.clockTickH0. When the low bit overflows to 0, the high bits increment.
109	   */
110	  if (!(++sfucbuilder_M->Timing.clockTick0)) {
111	    ++sfucbuilder_M->Timing.clockTickH0;
112	  }
113	
114	  sfucbuilder_M->Timing.taskTime0 = sfucbuilder_M->Timing.clockTick0 *
115	    sfucbuilder_M->Timing.stepSize0 + sfucbuilder_M->Timing.clockTickH0 *
116	    sfucbuilder_M->Timing.stepSize0 * 4294967296.0;
117	}
118	
119	/* Model initialize function */
120	void sfucbuilder_initialize(void)
121	{
122	  /* Registration code */
123	
124	  /* initialize non-finites */
125	  rt_InitInfAndNaN(sizeof(real_T));
126	
127	  /* initialize real-time model */
128	  (void) memset((void *)sfucbuilder_M, 0,
129	                sizeof(RT_MODEL_sfucbuilder_T));
130	  rtmSetTFinal(sfucbuilder_M, 10.0);
131	  sfucbuilder_M->Timing.stepSize0 = 0.001;
132	
133	  /* Setup for data logging */
134	  {
135	    static RTWLogInfo rt_DataLoggingInfo;
136	    rt_DataLoggingInfo.loggingInterval = NULL;
137	    sfucbuilder_M->rtwLogInfo = &rt_DataLoggingInfo;
138	  }
139	
140	  /* Setup for data logging */
141	  {
142	    rtliSetLogXSignalInfo(sfucbuilder_M->rtwLogInfo, (NULL));
143	    rtliSetLogXSignalPtrs(sfucbuilder_M->rtwLogInfo, (NULL));
144	    rtliSetLogT(sfucbuilder_M->rtwLogInfo, "tout");
145	    rtliSetLogX(sfucbuilder_M->rtwLogInfo, "");
146	    rtliSetLogXFinal(sfucbuilder_M->rtwLogInfo, "");
147	    rtliSetLogVarNameModifier(sfucbuilder_M->rtwLogInfo, "rt_");
148	    rtliSetLogFormat(sfucbuilder_M->rtwLogInfo, 0);
149	    rtliSetLogMaxRows(sfucbuilder_M->rtwLogInfo, 0);
150	    rtliSetLogDecimation(sfucbuilder_M->rtwLogInfo, 1);
151	    rtliSetLogY(sfucbuilder_M->rtwLogInfo, "");
152	    rtliSetLogYSignalInfo(sfucbuilder_M->rtwLogInfo, (NULL));
153	    rtliSetLogYSignalPtrs(sfucbuilder_M->rtwLogInfo, (NULL));
154	  }
155	
156	  /* block I/O */
157	  (void) memset(((void *) &sfucbuilder_B), 0,
158	                sizeof(B_sfucbuilder_T));
159	
160	  /* states (dwork) */
161	  (void) memset((void *)&sfucbuilder_DW, 0,
162	                sizeof(DW_sfucbuilder_T));
163	
164	  /* Matfile logging */
165	  rt_StartDataLoggingWithStartTime(sfucbuilder_M->rtwLogInfo, 0.0, rtmGetTFinal
166	    (sfucbuilder_M), sfucbuilder_M->Timing.stepSize0, (&rtmGetErrorStatus
167	    (sfucbuilder_M)));
168	
169	  /* InitializeConditions for UnitDelay: '<S1>/Output' */
170	  sfucbuilder_DW.Output_DSTATE = 0U;
171	
172	  /* InitializeConditions for S-Function (DFT_CMexSfuncBuilder): '<Root>/S-Function Builder' */
173	
174	  /* S-Function Block: <Root>/S-Function Builder */
175	  {
176	    real_T initVector[5] = { 1, 0, 0, 0, 50.0 };
177	
178	    {
179	      int_T i1;
180	      real_T *dw_DSTATE = &sfucbuilder_DW.SFunctionBuilder_DSTATE[0];
181	      for (i1=0; i1 < 5; i1++) {
182	        dw_DSTATE[i1] = initVector[i1];
183	      }
184	    }
185	  }
186	
187	  /* InitializeConditions for S-Function (DFT_CMexSfuncBuilder): '<Root>/S-Function Builder1' */
188	
189	  /* S-Function Block: <Root>/S-Function Builder1 */
190	  {
191	    real_T initVector[5] = { 1, 0, 0, 0, 50.0 };
192	
193	    {
194	      int_T i1;
195	      real_T *dw_DSTATE = &sfucbuilder_DW.SFunctionBuilder1_DSTATE[0];
196	      for (i1=0; i1 < 5; i1++) {
197	        dw_DSTATE[i1] = initVector[i1];
198	      }
199	    }
200	  }
201	}
202	
203	/* Model terminate function */
204	void sfucbuilder_terminate(void)
205	{
206	  /* (no terminate code required) */
207	}
208	

        人工检查上述自动生成的C代码,可以实现该Simulink模型设计的功能。

        至此,可以证明该S-Fuction Buider模块可以较好地实现,手动开发TLC相同的功能。

Tips

        本文沿用的例子--DFT算法S-Fuction开发,涉及到一个参数Freq。按照前期C MEX S-Function开发的经验,是可以通过函数直接引用的Freq = (real_T) *mxGetPr(ssGetSFcnParam(S,0)),但是在S-Fuction Buider里边尝试直接应用参数Freq时,却出现了报错。查阅相关资料后,发现有人是先把参数作为初始值赋给一个状态变量,然后再拿这个状态变量作为参数使用。本文中的第5个状态变量xD[4]就是充当Freq的中转桥,经验证这种方法确实可行。虽然这种方法稍微有点绕弯,但是也不失是一种解决问题的办法。

分析和应用

        前面分析了那么多C MEX S-Function和TLC的特点和应用,本文S-Fuction Buider是集它们特点于一身的存在,并且把C MEX S-Function中复杂的接口函数和TLC中复杂的语法,都变成了Matlab后台自动执行的工作,开发者只需把注意力集中在C算法的移植上即可,大大提升了S-Function开发的工作效率。

总结

        以上就是本人在使用S-Fuction Buider时,一些个人理解和分析的总结,首先介绍了S-Fuction Buider的基本知识,然后展示它的使用方法,最后分析了该模块的特点和适用场景。

        后续还会分享另外几个最近总结的Simulink Toolbox库模块,欢迎评论区留言、点赞、收藏和关注,这些鼓励和支持都将成文本人持续分享的动力。

        另外,上述例程使用的Demo工程,可以到笔者的主页查找和下载。


版权声明,原创文章,转载和引用请注明出处和链接,侵权必究!

这篇关于开箱报告,Simulink Toolbox库模块使用指南(七)——S-Fuction Builder模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/CSSUST/article/details/133564049
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/210409

相关文章

Java JSQLParser解析SQL的使用指南

《JavaJSQLParser解析SQL的使用指南》JSQLParser是一个Java语言的SQL语句解析工具,可以将SQL语句解析成为Java类的层次结构,还支持改写SQL,下面我们就来看看它的具... 目录一、引言二、jsQLParser常见类2.1 Class Diagram2.2 Statement

正则表达式r前缀使用指南及如何避免常见错误

《正则表达式r前缀使用指南及如何避免常见错误》正则表达式是处理字符串的强大工具,但它常常伴随着转义字符的复杂性,本文将简洁地讲解r的作用、基本原理,以及如何在实际代码中避免常见错误,感兴趣的朋友一... 目录1. 字符串的双重翻译困境2. 为什么需要 r?3. 常见错误和正确用法4. Unicode 转换的

Python logging模块使用示例详解

《Pythonlogging模块使用示例详解》Python的logging模块是一个灵活且强大的日志记录工具,广泛应用于应用程序的调试、运行监控和问题排查,下面给大家介绍Pythonlogging模... 目录一、为什么使用 logging 模块?二、核心组件三、日志级别四、基本使用步骤五、快速配置(bas

Python Selenium动态渲染页面和抓取的使用指南

《PythonSelenium动态渲染页面和抓取的使用指南》在Web数据采集领域,动态渲染页面已成为现代网站的主流形式,本文将从技术原理,环境配置,核心功能系统讲解Selenium在Python动态... 目录一、Selenium技术架构解析二、环境搭建与基础配置1. 组件安装2. 驱动配置3. 基础操作模

Spring Validation中9个数据校验工具使用指南

《SpringValidation中9个数据校验工具使用指南》SpringValidation作为Spring生态系统的重要组成部分,提供了一套强大而灵活的数据校验机制,本文给大家介绍了Spring... 目录1. Bean Validation基础注解常用注解示例在控制器中应用2. 自定义约束验证器定义自

Python datetime 模块概述及应用场景

《Pythondatetime模块概述及应用场景》Python的datetime模块是标准库中用于处理日期和时间的核心模块,本文给大家介绍Pythondatetime模块概述及应用场景,感兴趣的朋... 目录一、python datetime 模块概述二、datetime 模块核心类解析三、日期时间格式化与

Python如何调用指定路径的模块

《Python如何调用指定路径的模块》要在Python中调用指定路径的模块,可以使用sys.path.append,importlib.util.spec_from_file_location和exe... 目录一、sys.path.append() 方法1. 方法简介2. 使用示例3. 注意事项二、imp

Python中模块graphviz使用入门

《Python中模块graphviz使用入门》graphviz是一个用于创建和操作图形的Python库,本文主要介绍了Python中模块graphviz使用入门,具有一定的参考价值,感兴趣的可以了解一... 目录1.安装2. 基本用法2.1 输出图像格式2.2 图像style设置2.3 属性2.4 子图和聚

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中