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

news2025/1/21 22:03:28

文章目录

前言

Target Language Compiler(TLC)

C MEX S-Function模块

编写TLC文件

生成代码

Tips

分析和应用

总结


前言

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

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

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

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

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

Target Language CompilerTLC

        目标语言编译器(Target Language Compiler)代码生成器的重要组成部分。Mathworks官方Help对该部分内容的说明如下所示。

        在使用Simulink自动生成代码时,Library中自带的模块可以顺利的生成代码,但是如果用户在Model中用到了自己开发的C MEX S-Function模块,Simulink就不知道这个模块如何生成代码了。TLC文件的作用就是,告诉Simulink自己想把C MEX S-Function模块生成一些什么样的代码,以及如何与Model中的其他内容互联融合。TLC及模型代码的生成过程如下图所示:

        本文继续以DFT算法为例,介绍如何编写一个TLC文件,将C MEX S-Function模块生成代码

C MEX S-Function模块

        DFT算法的原理讲解和C MEX S-Function模块的开发在上一篇文章中已经完成了,见 《开箱报告,Simulink Toolbox库模块使用指南(五)——S-Fuction模块(C MEX S-Function)》。到这里仅仅是在Simulink中仿真时可以使用这样一个算法模块,本文是要把他生成C代码。由于算法中涉及了4个状态变量,对应到C语言中就要定义一组全局变量,这在TLC文件中实现会稍微麻烦一些。为了简化该过程,让大家更好地理解TLC,笔者对原有的C MEX S-Function模块进行了一些调整,将全局变量的定义放到了模块外面。如下图所示:

        DFT_CMexSfunc.c中对应代码的调整如下:

//增加一个输入端口
if (!ssSetNumInputPorts(S, 2)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortWidth(S, 1, 4); //新增的输入端口有4个信号

//增加一个输出端口
if (!ssSetNumOutputPorts(S, 2)) return; 
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortWidth(S, 1, 4); //新增的输处端口有4个信号

        DFT_CMexSfunc.c调整后需要用mex命令重新编译,如下图所示:

编写TLC文件

        在Model的Workspace文件夹下,新建一个DFT_CMexSfunc.tlc文件,编写tlc代码。写好后的完整内容如下,各部分代码的解释,以注释形式标注在对应位置。

%implements "DFT_CMexSfunc" "C"//与C MEX S-Function模块相对应
 
%% Function: Outputs
%function Outputs(block, system) Output//定义一个输出函数
 
%assign u = LibBlockInputSignal(0,"","",0)//获取输入信号
%assign u_count = LibBlockInputSignal(1,"","",0)
%assign u_t = LibBlockInputSignal(1,"","",1)
%assign u_cos_integ = LibBlockInputSignal(1,"","",2)
%assign u_sin_integ = LibBlockInputSignal(1,"","",3)
 
%assign y = LibBlockOutputSignal(0,"","",0) //获取输出信号
%assign y_count = LibBlockOutputSignal(1,"","",0)
%assign y_t = LibBlockOutputSignal(1,"","",1)
%assign y_cos_integ = LibBlockOutputSignal(1,"","",2)
%assign y_sin_integ = LibBlockOutputSignal(1,"","",3)

/%下面是要为C MEX S-Function模块生成的代码%/
if(%<u_count> < 5e3)//为了降低TLC复杂度,将常量L的值5e3直接写出来
{  
    %<y_cos_integ> = %<u_cos_integ> + %<u>*cos(2*3.14 * 50*%<u_t>);//将常量Freq的值50直接写出来
    %<y_sin_integ> = %<u_sin_integ> + %<u>*sin(2*3.14 * 50*%<u_t>);
    
    %<y_t> = %<u_t> + 1/10e3; //将常量Fs的值10e3直接写出来
    %<y_count> = %<u_count> + 1;
}
else if(%<u_count> == 5e3)
{
    %<y> = sqrt((%<u_cos_integ>/L*2)^2 + (%<u_sin_integ>/L*2)^2); //将过程变量real和imag用对应公式直接写出来
    %<y_count> = %<u_count> + 1;//避免无效运行消耗资源
}
else
{}
 
%endfunction//结束函数定义

        DFT_CMexSfunc.tlc文件保存在对应的路径下即可,不需要做额外的编译操作。

生成代码

        C MEX S-Function模块调整后对应的完整模型如下:

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

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

        点击左侧的sfucdemo.c超链接,可以看到如下生成的代码,其中30行到140行是该模型主要功能的代码,40行到53行是与我们C MEX S-Function模块直接相关的代码。

File: sfucdemo.c
1	/*
2	 * sfucdemo.c
3	 *
4	 * Code generation for model "sfucdemo".
5	 *
6	 * Model version              : 1.45
7	 * Simulink Coder version : 9.4 (R2020b) 29-Jul-2020
8	 * C source code generated on : Sun Sep 10 14:44:22 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 "sfucdemo.h"
18	#include "sfucdemo_private.h"
19	
20	/* Block signals (default storage) */
21	B_sfucdemo_T sfucdemo_B;
22	
23	/* Block states (default storage) */
24	DW_sfucdemo_T sfucdemo_DW;
25	
26	/* Real-time model */
27	static RT_MODEL_sfucdemo_T sfucdemo_M_;
28	RT_MODEL_sfucdemo_T *const sfucdemo_M = &sfucdemo_M_;
29	
30	/* Model step function */
31	void sfucdemo_step(void)
32	{
33	  /* Selector: '<Root>/Selector2' incorporates:
34	   *  Constant: '<Root>/Constant2'
35	   *  UnitDelay: '<S1>/Output'
36	   */
37	  sfucdemo_B.Selector2 =
38	    sfucdemo_ConstP.Constant2_Value[sfucdemo_DW.Output_DSTATE];
39	
40	  /* S-Function (DFT_CMexSfunc): '<Root>/S-Function3' */
41	  if (sfucdemo_B.Memory[0] < 5e3) {
42	    sfucdemo_B.SFunction3_o2[2] = sfucdemo_B.Memory[2] + sfucdemo_B.Selector2*
43	      cos(2*3.14 * 50*sfucdemo_B.Memory[1]);
44	    sfucdemo_B.SFunction3_o2[3] = sfucdemo_B.Memory[3] + sfucdemo_B.Selector2*
45	      sin(2*3.14 * 50*sfucdemo_B.Memory[1]);
46	    sfucdemo_B.SFunction3_o2[1] = sfucdemo_B.Memory[1] + 1/10e3;
47	    sfucdemo_B.SFunction3_o2[0] = sfucdemo_B.Memory[0] + 1;
48	  } else if (sfucdemo_B.Memory[0] == 5e3) {
49	    sfucdemo_B.SFunction3_o1 = sqrt((sfucdemo_B.Memory[2]/L*2)^2 +
50	      (sfucdemo_B.Memory[3]/L*2)^2);
51	    sfucdemo_B.SFunction3_o2[0] = sfucdemo_B.Memory[0] + 1;
52	  } else {
53	  }
54	
55	  /* Selector: '<Root>/Selector3' incorporates:
56	   *  Constant: '<Root>/Constant3'
57	   *  UnitDelay: '<S1>/Output'
58	   */
59	  sfucdemo_B.Selector3 =
60	    sfucdemo_ConstP.Constant3_Value[sfucdemo_DW.Output_DSTATE];
61	
62	  /* S-Function (DFT_CMexSfunc): '<Root>/S-Function4' */
63	  if (sfucdemo_B.Memory1[0] < 5e3) {
64	    sfucdemo_B.SFunction4_o2[2] = sfucdemo_B.Memory1[2] + sfucdemo_B.Selector3*
65	      cos(2*3.14 * 50*sfucdemo_B.Memory1[1]);
66	    sfucdemo_B.SFunction4_o2[3] = sfucdemo_B.Memory1[3] + sfucdemo_B.Selector3*
67	      sin(2*3.14 * 50*sfucdemo_B.Memory1[1]);
68	    sfucdemo_B.SFunction4_o2[1] = sfucdemo_B.Memory1[1] + 1/10e3;
69	    sfucdemo_B.SFunction4_o2[0] = sfucdemo_B.Memory1[0] + 1;
70	  } else if (sfucdemo_B.Memory1[0] == 5e3) {
71	    sfucdemo_B.SFunction4_o1 = sqrt((sfucdemo_B.Memory1[2]/L*2)^2 +
72	      (sfucdemo_B.Memory1[3]/L*2)^2);
73	    sfucdemo_B.SFunction4_o2[0] = sfucdemo_B.Memory1[0] + 1;
74	  } else {
75	  }
76	
77	  /* Switch: '<S3>/FixPt Switch' incorporates:
78	   *  Constant: '<S2>/FixPt Constant'
79	   *  Sum: '<S2>/FixPt Sum1'
80	   *  UnitDelay: '<S1>/Output'
81	   */
82	  if ((uint16_T)(sfucdemo_DW.Output_DSTATE + 1U) > 4999) {
83	    /* Update for UnitDelay: '<S1>/Output' incorporates:
84	     *  Constant: '<S3>/Constant'
85	     */
86	    sfucdemo_DW.Output_DSTATE = 0U;
87	  } else {
88	    /* Update for UnitDelay: '<S1>/Output' */
89	    sfucdemo_DW.Output_DSTATE++;
90	  }
91	
92	  /* End of Switch: '<S3>/FixPt Switch' */
93	
94	  /* Memory: '<Root>/Memory' */
95	  sfucdemo_B.Memory[0] = sfucdemo_DW.Memory_PreviousInput[0];
96	
97	  /* Memory: '<Root>/Memory1' */
98	  sfucdemo_B.Memory1[0] = sfucdemo_DW.Memory1_PreviousInput[0];
99	
100	  /* Update for Memory: '<Root>/Memory' */
101	  sfucdemo_DW.Memory_PreviousInput[0] = sfucdemo_B.SFunction3_o2[0];
102	
103	  /* Update for Memory: '<Root>/Memory1' */
104	  sfucdemo_DW.Memory1_PreviousInput[0] = sfucdemo_B.SFunction4_o2[0];
105	
106	  /* Memory: '<Root>/Memory' */
107	  sfucdemo_B.Memory[1] = sfucdemo_DW.Memory_PreviousInput[1];
108	
109	  /* Memory: '<Root>/Memory1' */
110	  sfucdemo_B.Memory1[1] = sfucdemo_DW.Memory1_PreviousInput[1];
111	
112	  /* Update for Memory: '<Root>/Memory' */
113	  sfucdemo_DW.Memory_PreviousInput[1] = sfucdemo_B.SFunction3_o2[1];
114	
115	  /* Update for Memory: '<Root>/Memory1' */
116	  sfucdemo_DW.Memory1_PreviousInput[1] = sfucdemo_B.SFunction4_o2[1];
117	
118	  /* Memory: '<Root>/Memory' */
119	  sfucdemo_B.Memory[2] = sfucdemo_DW.Memory_PreviousInput[2];
120	
121	  /* Memory: '<Root>/Memory1' */
122	  sfucdemo_B.Memory1[2] = sfucdemo_DW.Memory1_PreviousInput[2];
123	
124	  /* Update for Memory: '<Root>/Memory' */
125	  sfucdemo_DW.Memory_PreviousInput[2] = sfucdemo_B.SFunction3_o2[2];
126	
127	  /* Update for Memory: '<Root>/Memory1' */
128	  sfucdemo_DW.Memory1_PreviousInput[2] = sfucdemo_B.SFunction4_o2[2];
129	
130	  /* Memory: '<Root>/Memory' */
131	  sfucdemo_B.Memory[3] = sfucdemo_DW.Memory_PreviousInput[3];
132	
133	  /* Memory: '<Root>/Memory1' */
134	  sfucdemo_B.Memory1[3] = sfucdemo_DW.Memory1_PreviousInput[3];
135	
136	  /* Update for Memory: '<Root>/Memory' */
137	  sfucdemo_DW.Memory_PreviousInput[3] = sfucdemo_B.SFunction3_o2[3];
138	
139	  /* Update for Memory: '<Root>/Memory1' */
140	  sfucdemo_DW.Memory1_PreviousInput[3] = sfucdemo_B.SFunction4_o2[3];
141	
142	  /* Matfile logging */
143	  rt_UpdateTXYLogVars(sfucdemo_M->rtwLogInfo, (&sfucdemo_M->Timing.taskTime0));
144	
145	  /* signal main to stop simulation */
146	  {                                    /* Sample time: [0.001s, 0.0s] */
147	    if ((rtmGetTFinal(sfucdemo_M)!=-1) &&
148	        !((rtmGetTFinal(sfucdemo_M)-sfucdemo_M->Timing.taskTime0) >
149	          sfucdemo_M->Timing.taskTime0 * (DBL_EPSILON))) {
150	      rtmSetErrorStatus(sfucdemo_M, "Simulation finished");
151	    }
152	  }
153	
154	  /* Update absolute time for base rate */
155	  /* The "clockTick0" counts the number of times the code of this task has
156	   * been executed. The absolute time is the multiplication of "clockTick0"
157	   * and "Timing.stepSize0". Size of "clockTick0" ensures timer will not
158	   * overflow during the application lifespan selected.
159	   * Timer of this task consists of two 32 bit unsigned integers.
160	   * The two integers represent the low bits Timing.clockTick0 and the high bits
161	   * Timing.clockTickH0. When the low bit overflows to 0, the high bits increment.
162	   */
163	  if (!(++sfucdemo_M->Timing.clockTick0)) {
164	    ++sfucdemo_M->Timing.clockTickH0;
165	  }
166	
167	  sfucdemo_M->Timing.taskTime0 = sfucdemo_M->Timing.clockTick0 *
168	    sfucdemo_M->Timing.stepSize0 + sfucdemo_M->Timing.clockTickH0 *
169	    sfucdemo_M->Timing.stepSize0 * 4294967296.0;
170	}
171	
172	/* Model initialize function */
173	void sfucdemo_initialize(void)
174	{
175	  /* Registration code */
176	
177	  /* initialize non-finites */
178	  rt_InitInfAndNaN(sizeof(real_T));
179	
180	  /* initialize real-time model */
181	  (void) memset((void *)sfucdemo_M, 0,
182	                sizeof(RT_MODEL_sfucdemo_T));
183	  rtmSetTFinal(sfucdemo_M, 10.0);
184	  sfucdemo_M->Timing.stepSize0 = 0.001;
185	
186	  /* Setup for data logging */
187	  {
188	    static RTWLogInfo rt_DataLoggingInfo;
189	    rt_DataLoggingInfo.loggingInterval = NULL;
190	    sfucdemo_M->rtwLogInfo = &rt_DataLoggingInfo;
191	  }
192	
193	  /* Setup for data logging */
194	  {
195	    rtliSetLogXSignalInfo(sfucdemo_M->rtwLogInfo, (NULL));
196	    rtliSetLogXSignalPtrs(sfucdemo_M->rtwLogInfo, (NULL));
197	    rtliSetLogT(sfucdemo_M->rtwLogInfo, "tout");
198	    rtliSetLogX(sfucdemo_M->rtwLogInfo, "");
199	    rtliSetLogXFinal(sfucdemo_M->rtwLogInfo, "");
200	    rtliSetLogVarNameModifier(sfucdemo_M->rtwLogInfo, "rt_");
201	    rtliSetLogFormat(sfucdemo_M->rtwLogInfo, 0);
202	    rtliSetLogMaxRows(sfucdemo_M->rtwLogInfo, 0);
203	    rtliSetLogDecimation(sfucdemo_M->rtwLogInfo, 1);
204	    rtliSetLogY(sfucdemo_M->rtwLogInfo, "");
205	    rtliSetLogYSignalInfo(sfucdemo_M->rtwLogInfo, (NULL));
206	    rtliSetLogYSignalPtrs(sfucdemo_M->rtwLogInfo, (NULL));
207	  }
208	
209	  /* block I/O */
210	  (void) memset(((void *) &sfucdemo_B), 0,
211	                sizeof(B_sfucdemo_T));
212	
213	  /* states (dwork) */
214	  (void) memset((void *)&sfucdemo_DW, 0,
215	                sizeof(DW_sfucdemo_T));
216	
217	  /* Matfile logging */
218	  rt_StartDataLoggingWithStartTime(sfucdemo_M->rtwLogInfo, 0.0, rtmGetTFinal
219	    (sfucdemo_M), sfucdemo_M->Timing.stepSize0, (&rtmGetErrorStatus(sfucdemo_M)));
220	
221	  /* InitializeConditions for UnitDelay: '<S1>/Output' */
222	  sfucdemo_DW.Output_DSTATE = 0U;
223	
224	  /* InitializeConditions for Memory: '<Root>/Memory' */
225	  sfucdemo_DW.Memory_PreviousInput[0] = 0.0;
226	
227	  /* InitializeConditions for Memory: '<Root>/Memory1' */
228	  sfucdemo_DW.Memory1_PreviousInput[0] = 0.0;
229	
230	  /* InitializeConditions for Memory: '<Root>/Memory' */
231	  sfucdemo_DW.Memory_PreviousInput[1] = 0.0;
232	
233	  /* InitializeConditions for Memory: '<Root>/Memory1' */
234	  sfucdemo_DW.Memory1_PreviousInput[1] = 0.0;
235	
236	  /* InitializeConditions for Memory: '<Root>/Memory' */
237	  sfucdemo_DW.Memory_PreviousInput[2] = 0.0;
238	
239	  /* InitializeConditions for Memory: '<Root>/Memory1' */
240	  sfucdemo_DW.Memory1_PreviousInput[2] = 0.0;
241	
242	  /* InitializeConditions for Memory: '<Root>/Memory' */
243	  sfucdemo_DW.Memory_PreviousInput[3] = 0.0;
244	
245	  /* InitializeConditions for Memory: '<Root>/Memory1' */
246	  sfucdemo_DW.Memory1_PreviousInput[3] = 0.0;
247	}
248	
249	/* Model terminate function */
250	void sfucdemo_terminate(void)
251	{
252	  /* (no terminate code required) */
253	}
254	

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

        至此,可以证明该TLC文件可以较好地生成C MEX S-Fuction模块的自动代码。

Tips

        TLC的特殊性在于,它本身是一种编程语言,具有文本类编程语言的大部分特点,同时它要实现的功能又是控制C或C++另一种文本语言代码的生成,所以TLC的开发必须熟练掌握它特有的语法结构,常见的一些基础语法如下。

        1、%,TLC指令开始的标志符。

        2、%implements,一个模块的TLC文件要执行的第一条指令,不可省略。

        3、%function,声明一个函数,要配合%endfunction使用。

        4、%assign,创建变量。

        5、函数LibBlockInputSignal(portIdx, "","",sigIdx),返回模块的输入信号,portIdx和sigIdx都从0开始计数。

        6、函数LibBlockOutputSignal(portIdx, "","",sigIdx),返回模块的输出信号。

        7、函数LibBlockParameterValue(param, elIdx),返回模块的参数值。

        8、<>,TLC表达式的开始和结束。

        9、%%和/%   %/,注释。

分析和应用

        本文上述内容中看到,TLC实现了C MEX S-Fuction模块的代码生成,但是进一步仔细研究发现,Library中自带的模块的代码生成也是由TLC实现的,甚至生成代码的总体结构也是由TLC实现的,这些模块的TLC文件就存放在Matlab的系统路径ProgramFiles\Matlab2020b\rtw\c\tlc下。

        所以说Simulink的自动代码生成过程,并不是完全固定死的,当我们有特定需求时,可以通过调整TLC文件的内容来实现的。这样就给了代码开发工程师们在代码生成方面的灵活度和自由度,为Simulink的自动代码生成提供了无限可能。

总结

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

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

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


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/996670.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity中Shader抓取屏幕并实现扭曲效果实现

文章目录 前言一、屏幕抓取&#xff0c;在上一篇文章已经写了二、实现抓取后的屏幕扭曲实现思路&#xff1a;1、屏幕扭曲要借助传入 UV 贴图进行扭曲2、传入贴图后在顶点着色器的输入参数处&#xff0c;传入一个 float2 uv : TEXCOORD&#xff0c;用于之后对扭曲贴图进行采样3、…

【鲁棒电力系统状态估计】基于投影统计的电力系统状态估计的鲁棒GM估计器(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Orangepi Zero2 全志H616(一):配置初始化和启动流程

目录 一&#xff0c;Orangepi简单说明 ①为什么使用全志H616 ②基本特性 ③配套操作系统支持 二&#xff0c;刷机和系统启动 ①准备工具 ②登录系统 ● 开发板供电 ● 登录 ● 开发板上板载LED灯测试说明 ③修改登录密码 ④网络配置 ⑤SSH登陆开发板 三&#xff…

(二十六)大数据实战——kafka集群之Kraft模式安装与部署

前言 本节内容主要介绍kafka3.0版本以后&#xff0c;一种新的kafka集群搭建模式看kraft&#xff0c;在该模式下&#xff0c;kafka高可用不在依赖于zookeeper&#xff0c;用 controller 节点代替 zookeeper&#xff0c;元数据保存在 controller 中&#xff0c;由 controller 直…

产品路线图管理,实践如何管理产品路线图和路线图规划

​什么是产品路线图&#xff1f; 产品路线图是一个高层次的战略计划&#xff0c;它描述了产品在未来一段时间可能会如何发展和壮大。 产品路线图确保整个产品团队持续关注产品的目标&#xff0c;帮助产品负责人把握产品的战略方向&#xff0c;调整产品的优先级和产品规划。 …

【实践篇】Redis最强Java客户端Redisson

文章目录 1. 前言2. Redisson基础概念2.1 数据结构和并发工具2.1.1 对Redis原生数据类型的封装和使用2.1.2 分布式锁实现和应用2.1.3 分布式集合使用方法 2.2 Redisson的高级特性2.2.1 分布式对象实现和使用2.2.2 分布式消息队列实现和使用2.2.3 分布式计数器实现和使用 3. 参考…

hadoop伪分布模式配置

1、修改/usr/local/hadoop/etc/hadoop/core-site.xml和/usr/local/hadoop/etc/hadoop/hdfs-site.xml文件 core-site.xml内容 <configuration><property><name>hadoop.tmp.dir</name><value>file:/usr/local/hadoop/tmp</value><descr…

日志平台搭建第四章:Linux安装kibana

相关链接 https://www.elastic.co/cn/downloads/kibana https://artifacts.elastic.co/downloads/kibana/kibana-7.5.1-linux-x86_64.tar.gz 官网下载可能比较慢&#xff0c;下面提供下载地址 百度云链接&#xff1a;https://pan.baidu.com/s/1d9Cqr9EwHF94op90F57bww 提取码…

《微服务架构设计模式》第二章

文章目录 微服务架构是什么软件架构是什么软件架构的定义软件架构的41视图模型为什么架构如此重要 什么是架构风格分层式架构风格六边形架构风格微服务架构风格 为应用程序定义微服务架构识别操作系统根据业务能力进行拆分根据子域进行拆分拆分指导原则单一职责原则&#xff08…

idea的GsonFormatPlus插件教程

1 安装 插件 打开idea, File—>Setting—>Plugins,搜索 GsonFormatPlus 直接安装 2 json 转化为 实体类 2.1 新建一个类 2.2 点击右键 2.4 点击Format 生成注释

聊一下酱香拿铁,瑞幸与茅台强强联手

&#xff08;点击即可收听&#xff09; 这两天&#xff0c;酱香拿铁火爆朋友圈了的 为什么唯独酱香拿铁会火成这样&#xff0c;不知道有人思考过背后逻辑&#xff1f; 难道只是因为一个新出的拿铁咖啡吗&#xff1f; 奇葩咖啡那么多为什么都没有这个一出来就爆火。 联名本身就是…

BUUCTF内涵的软件 1

使用die查看文件信息&#xff0c;没有pe64就是pe32 运行看看 使用IDA打开文件 shift F12 打开字符串窗口 可能有人猜到了上面的 DBAPP{49d3c93df25caad81232130f3d2ebfad} 可能就是flag&#xff0c;但是我们保持做题的思路来得到这个flag 因为编码问题&#xff0c;这里显…

第29节-PhotoShop基础课程-滤镜库

文章目录 前言1.滤镜库2.Camera Raw滤镜 &#xff08;用来对图片进行预处理&#xff0c;最全面的一个&#xff09;3.神经滤镜&#xff08;2022插件 需要先下载&#xff09;4.液化&#xff08;胖-> 瘦 矮->高&#xff09;5.其它滤镜1.自适应广角2.镜头矫正 把图片放正3.消…

分享配置FreeRTOSConfig.h文件因部分宏值配置不对以及相应函数未定义出现的三个错误解决方法

今天来分享一个在创建FreeRTOS时候调用官方的FreeRTOSConfig头文件时&#xff0c;因部分宏值的配置与FreeRTOS内核文件中的函数不匹配&#xff0c;导致编译时候出现了相应的错误。 于是&#xff0c;既然遇到了&#xff0c;就准备拿出来讲一下&#xff0c;让其他遇到的小伙伴也…

VBA技术资料MF55:VBA_突出显示小于某值的单元格

【分享成果&#xff0c;随喜正能量】当你对别人有用时&#xff0c;人性就是善良的&#xff1b;当你对别人无用时&#xff0c;人性就是自私的&#xff1b;当你触碰别人利益时&#xff0c;人性就是恶毒的。活得通透的人必须做到&#xff1a;圈子越来越小&#xff0c;话也越来越少…

解决transform带来的z-index失效问题

现象如下&#xff1a; 其实下拉列表已经设置了z-index: 但是为什么z-index没有生效呢。 后来发现原来它的父级元素使用了transform进行垂直方向居中 网上查询了相关资料&#xff0c;说: tranform由于会构造一个新的context层, 然后这个层的z轴优先级会最低巴拉巴拉的&#xff…

通信原理板块——信道之无线信道和有线信道

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 1、信道 通信模型中的信道&#xf…

初探JVM

五道常问面试题 1.请你谈谈你对JVM的理解&#xff1f;java8虚拟机和之前的变化更新&#xff1f; 2.什么是OOM,什么是栈溢出StackOverFlowError?怎么分析? 3.JVM的常用调优参数有哪些&#xff1f; 4.内存快照如何抓取&#xff0c;怎么分析Dump文件&#xff1f;知道吗&#xf…

队列(Queue)的顶级理解

目录 1.队列(Queue) 的概念 2.单链表模拟实现队列 2.1创建队列 2.2入队列 2.3判断是否为空 2.4出队列 2.5获取队头元素 2.6完整代码&#xff1a; 2.7双向链表模拟实现队列代码 3.数组模拟实现队列代码 3.1创建队列 3.2判断是否为满 3.3检查是否为空 3.4插入元素 3…

时序分解 | MATLAB实现RIME-VMD霜冰优化算法优化VMD变分模态分解信号分量可视化

时序分解 | MATLAB实现RIME-VMD霜冰优化算法优化VMD变分模态分解信号分量可视化 目录 时序分解 | MATLAB实现RIME-VMD霜冰优化算法优化VMD变分模态分解信号分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 RIME-VMD【23年新算法】霜冰优化算法优化VMD变分模态分…