通过外部代码定义的指针访问结构化数据
此示例演示如何生成使用一些手写代码定义的全局数据的代码。在手写代码中,指针变量指向包含参数数据的三个结构变量之一。手写函数在结构之间切换指针。生成的代码通过解引用指针变量来访问参数数据。
探索外部代码
打开示例源文件rtwdemo_importstruct_user.c
.代码定义了一个默认的数据结构变量ReferenceStruct
作为常数(常量
)数据,并静态初始化每个字段。该结构表示参考数据集。
/*固定的默认数据结构(引用数据集)*/ const DataStruct_type ReferenceStruct = {11, /* OFFSET */ 2 /* GAIN */};
该代码定义了另外两个结构变量,WorkingStruct1
和WorkingStruct2
,为易挥发的(挥发性
)数据。
/* Volatile数据结构(工作数据集)*/ Volatile DataStruct_type WorkingStruct1;volatile DataStruct_type WorkingStruct2
该代码定义了一个可以初始化的函数:
由主动工作结构转化为非活动工作结构。
两个工作结构都来自参考结构。
/*从活动结构中初始化非活动工作结构的函数*/ void InitInactiveWorkingStructs(void) {if (StructPointer == &WorkingStruct1){/*从WorkingStruct1中复制值到WorkingStruct2 */ memcpy((void*)&WorkingStruct2, (void*)&WorkingStruct1, sizeof(ReferenceStruct));} else if (StructPointer == &WorkingStruct2){/*从WorkingStruct2复制值到WorkingStruct1 */ memcpy((void*)&WorkingStruct1, (void*)&WorkingStruct2, sizeof(ReferenceStruct));} else{/*初始化ReferenceStruct */ memcpy中的两个工作结构((void*)&WorkingStruct1, &ReferenceStruct, sizeof(ReferenceStruct));memcpy((void*)&WorkingStruct2, &ReferenceStruct, sizeof(ReferenceStruct));}}
代码定义了StructPointer
,这是一个常量不稳定
指向结构的指针。的地址的指针初始化ReferenceStruct
.
/*定义结构指针。*/ const volatile DataStruct_type *StructPointer = &ReferenceStruct
最后,代码定义了一个可以动态设置的函数StructPointer
指向任何一个ReferenceStruct
,WorkingStruct1
,或WorkingStruct2
.
/*在结构之间切换的函数*/ void SwitchStructPointer(Dataset_T Dataset) {switch (Dataset) {case Working1: StructPointer = &WorkingStruct1;打破;case Working2: StructPointer = &WorkingStruct2;打破;default: StructPointer = &ReferenceStruct;}}
示例头文件rtwdemo_importstruct_user.h
定义枚举。Dataset_T
以及结构类型Datastruct_type
.该文件包括(# include
)内置的Simulink®Co金宝appder™头文件rtwtypes.h
,它定义了(类型定义
) 金宝appSimulink Coder数据类型,例如int16_T
.
#include "rtwtypes.h" typedef enum {Reference = 0, Working1, Working2} Dataset_T;typedef struct DataStruct_tag {int16_T OFFSET;/*偏移量*/ int16_T增益;/* GAIN */} DataStruct_type;
该文件还声明了全局变量和函数。
外部代码的目的
该代码的设计目的是使控制算法的源代码(无论是生成的还是手写的)可以从ReferenceStruct
,WorkingStruct1
,或WorkingStruct2
取消引用(->
)StructPointer
.两个工作结构(WorkingStruct1
和WorkingStruct2
)位于易失性存储器中,并打算在运行期间通过外部校准工具进行更改。校准工程师不改变主动工作结构。相反,工程师改变非活动工作结构中的参数值,然后通过切换工作结构来激活它。
如果为了安全需要或为了准备关闭应用程序,校准工具可以指向StructPointer
来ReferenceStruct
代替。ReferenceStruct
存储在执行期间不更改的默认参数值。
探索范例模型
打开示例模型,rtwdemo_importstruct
.
模型在基本工作区中创建变量和对象。常量块和增益块使用ECoderDemos。参数
对象获得
和抵消
设置恒定值和获得块的参数。ECoderDemos
是一个定义了两个类的示例自定义包,参数
和信号
,以及一些自定义存储类。
在建模选项卡上,单击模型数据编辑器.
在模型数据编辑器中,检查参数选项卡。
设置改变观点下拉列表代码
.
单击显示/刷新附加信息按钮。
模型数据编辑器显示对应于恒定值和获得对应的块和行的参数抵消
和获得
,设置参数值。在存储类列,抵消
和获得
使用自定义存储类StructPointer
,而ECoderDemos
包定义。
中打开自定义存储类设计器并检查自定义存储类ECoderDemos
包中。在命令提示符处,使用以下命令:
cscdesigner (“ECoderDemos”)
这个示例包定义了多个自定义存储类,包括StructPointer
.您不能编辑定义。但是,您可以稍后创建自己的包和自定义存储类。有关演示如何创建包和自定义存储类的示例,请参见创建并应用存储类.
下自定义存储类定义,点击StructPointer
.这个自定义存储类的设置使生成的代码能够与指针变量交互,StructPointer
,从外部代码。例如,自定义存储类使用以下设置:
数据范围设置为
进口
因为示例外部代码定义(为)分配内存StructPointer
.使用此设置,代码生成器可以避免为数据项生成不必要的重复定义,例如ECoderDemos。参数
对象,使用自定义存储类。数据访问设置为
指针
因为在外部代码的例子中,StructPointer
是一个指针。记忆的部分设置为
ConstVolatile
因为示例外部代码定义StructPointer
作为常量、不稳定的数据(常量不稳定
).类型设置为
FlatStructure
因为在外部代码的例子中,StructPointer
指向一个结构。使用此设置,生成的代码处理每个数据项(ECoderDemos。参数
对象)作为平面结构的字段,您可以指定其变量名和类型名。在结构属性选项卡,结构体名称设置为
StructPointer
.对于一个FlatStructure
自定义存储类,结构体名称指定生成代码中结构变量的名称。在这个例子中,StructPointer
外部代码定义的变量的名称。类型名称设置为
DataStruct_type
,这是示例外部代码定义的结构类型的名称。
在模型中,在配置参数对话框,检查代码生成>自定义代码窗格。
下在生成中插入自定义C代码中,选择初始化函数.此参数值指定要包含在生成的模型初始化函数中的代码。在此模型中,设置了配置参数,以便生成的代码调用InitInactiveWorkingStructs
函数。InitInactiveWorkingStructs
的值初始化工作结构ReferenceStruct
.然后初始化代码将指针设置为第一个工作结构。
下其他构建信息中,选择源文件.此配置参数标识示例外部代码文件rtwdemo_importstruct_user.c
以便在代码生成后包含在构建过程中。
生成和检查代码
从模型生成代码。
在生成的文件中rtwdemo_importstruct.c
,模型初始化函数调用InitInactiveWorkingStructs
.
/*模型初始化函数*/ void rtwdemo_importstruct_initialize(void){/*用户代码(初始化函数体)*/ /*初始化工作结构为引用值*/ InitInactiveWorkingStructs();/*切换到第一个工作结构*/ SwitchStructPointer(Working1);} / *
模型执行中的算法(一步
函数解引用指针变量StructPointer
.
/*模型步长函数*/ void rtwdemo_importstruct_step(void) {/* Outport: '<根>/Out'合并:* Constant: '<根>/Offset' * Gain: '<根>/Gain' * Inport: '<根>/In' * Sum: '<根>/Sum' */ Sensor_Out = (int16_T)((int16_T)(Sensor_In - StructPointer-> Offset) * StructPointer-> Gain);}