文档

通过外部代码定义的指针访问结构化数据

此示例演示如何生成使用一些手写代码定义的全局数据的代码。在手写代码中,指针变量指向包含参数数据的三个结构变量之一。手写函数在结构之间切换指针。生成的代码通过解引用指针变量来访问参数数据。

探索外部代码

打开示例源文件rtwdemo_importstruct_user.c.代码定义了一个默认的数据结构变量ReferenceStruct作为常数(常量)数据,并静态初始化每个字段。该结构表示参考数据集。

/*固定的默认数据结构(引用数据集)*/ const DataStruct_type ReferenceStruct = {11, /* OFFSET */ 2 /* GAIN */};

该代码定义了另外两个结构变量,WorkingStruct1WorkingStruct2,为易挥发的(挥发性)数据。

/* 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指向任何一个ReferenceStructWorkingStruct1,或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;

该文件还声明了全局变量和函数。

外部代码的目的

该代码的设计目的是使控制算法的源代码(无论是生成的还是手写的)可以从ReferenceStructWorkingStruct1,或WorkingStruct2取消引用(->StructPointer.两个工作结构(WorkingStruct1WorkingStruct2)位于易失性存储器中,并打算在运行期间通过外部校准工具进行更改。校准工程师不改变主动工作结构。相反,工程师改变非活动工作结构中的参数值,然后通过切换工作结构来激活它。

如果为了安全需要或为了准备关闭应用程序,校准工具可以指向StructPointerReferenceStruct代替。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);}

相关的话题