主要内容

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

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

探索外部代码

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

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

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

/* Volatile数据结构(工作数据集)*/ Volatile DataStruct_type WorkingStruct1;挥发性DataStruct_type WorkingStruct2;

代码定义了可以初始化的函数:

  • 来自主动工作结构的非活动工作结构。

  • 两个工作结构都来自参考结构。

/ *函数从活动结构初始化非活动工作结构* / void initinactiveworkstructs(void){if(struitpointer ==&workstruct1){/ *从工作结构的拷贝值到工作结构2 * / memcpy((void *)和工作结构2,(void *)和工作结构1,sizeof(referencestruct));}如果(StructPointer ==&Worksstruct2){/ *从工作结构2复制到工作结构1 * / memcpy((void *)和工作结构1,(void *)和工作结构2,sizeof(推荐));} else {/ *初始化来自引用的工作结构* / memcpy((void *)&worksuction1,&carpencestuct,sizeof(参考要求));Memcpy((void *)和工作结构2,&referencestuct,sizeof(图表);}}

代码定义StructPointer,这是一个常量不稳定指向一个结构。代码将指针初始化到地址推荐人

/*定义结构指针。默认指向引用结构*/ const volatile DataStruct_type *StructPointer = &ReferenceStruct;

最后,代码定义了一个可以动态设置的函数StructPointer要点推荐人WorkingStruct1,或WorkingStruct2

/* void SwitchStructPointer(Dataset_T Dataset) {switch (Dataset) {case Working1: StructPointer = &WorkingStruct1;打破;case Working2: StructPointer = &WorkingStruct2;打破;默认:StructPointer = &ReferenceStruct;}}

示例头文件rtwdemo_importstruct_user.h定义枚举Dataset_T以及结构类型Datastruct_type.该文件包括(# include)内置Simulink®Cod金宝apper™头文件rtwtypes.h,其中定义(typedef.Si金宝appmulink Coder数据类型,例如int16_t.

#include“rtwtypes.h”typedef枚举{参考= 0,工作1,工作2} dataset_t;typedef struct dataStruct_tag {int16_t偏移;/ *偏移* / int16_t增益;/ * gain * /} dataStruct_type;

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

外部代码的目的

该代码的设计是为了使控制算法的源代码(无论是生成的还是手写的)可以读取数据推荐人WorkingStruct1,或WorkingStruct2由非关联化(- >StructPointer.两个工作结构(WorkingStruct1WorkingStruct2)位于易失性存储器中,旨在通过外部校准工具在运行时进行更改。校准工程师不会改变主动工作结构。相反,工程师在非活动工作结构中更改参数值,然后通过切换工作结构来激活它。

如有必要的话,安全或准备关闭应用程序,校准工具可以点StructPointer推荐人代替。推荐人存储在执行期间不会更改的默认参数值。

探索示例模型

打开示例模型,rtwdemo_importstruct

模型在基本工作区中创建变量和对象。常数块和增益块使用ECoderDemos。参数对象获得抵消设置恒定值获得块的参数。ECoderDemos是一个示例自定义包,定义了两个类,参数信号,以及一些自定义存储类。

建模选项卡上,单击模型数据编辑器

在模型数据编辑器中,检查参数标签。

设置改变视图下拉列表代码

点击显示/刷新其他信息按钮。

模型数据编辑器显示与恒定值获得块和行的参数对应于的块和行抵消获得,它设置参数值。在里面存储类柱子,抵消获得使用自定义存储类StructPointer,ECoderDemos包定义。

属性中的自定义存储类设计器并检查自定义存储类ECoderDemos包中。在命令提示符处,使用下面的命令:

cscdesigner (“ECoderDemos”

这个示例包定义了多个自定义存储类,包括StructPointer.您无法编辑定义。但是,您可以稍后创建自己的包和自定义存储类。有关显示如何创建包和自定义存储类的示例,请参阅创建并应用存储类

自定义存储类定义, 点击StructPointer.这个自定义存储类的设置允许生成的代码与指针变量交互,StructPointer,来自外部代码。例如,自定义存储类使用这些设置:

  • 数据范围被设定为进口因为示例外部代码定义(分配内存)StructPointer.使用此设置,代码生成器可以避免为数据项生成不必要的、重复的定义,例如ECoderDemos。参数对象,使用自定义存储类。

  • 数据访问被设定为指针因为在示例外部代码中,StructPointer是一个指针。

  • 记忆部分被设定为ConstVolatile因为示例外部代码定义StructPointer为常量、易失性数据(常量不稳定)。

  • 类型被设定为扁平结构因为在示例外部代码中,StructPointer指向一个结构。使用此设置,生成的代码会处理每个数据项(ECoderDemos。参数对象)作为平面结构的字段,可以指定其变量名和类型名。

  • 结构属性标签,结构名称被设定为StructPointer.对于一个扁平结构自定义存储类,结构名称指定生成的代码中的结构变量的名称。在这个例子中,StructPointer是外部代码定义的变量的名称。

  • 键入名称被设定为DataStruct_type,这是示例外部代码定义的结构类型的名称。

在模型中配置参数对话框,检查代码生成>自定义代码窗格。

在生成的中插入自定义C代码中,选择初始化函数.此参数值指定要包含在生成的模型初始化函数中的代码。在此模型中,设置了配置参数,以便生成的代码调用InitInactiveWorkingStructs函数。InitInactiveWorkingStructs使用的值初始化工作结构推荐人.然后,初始化代码将指针设置为第一个工作结构。

额外的构建信息中,选择源文件.此配置参数标识示例外部代码文件rtwdemo_importstruct_user.c在代码生成后包含在构建过​​程中。

生成和检查代码

从模型生成代码。

在生成的文件中rtwdemo_importstruct.c,模型初始化函数调用InitInactiveWorkingStructs

/ *模型初始化函数* / void RTWDEMO_IMPort_Initialize(void){/ *用户代码(初始化函数body)* // *初始化工作结构以引用值* / initInactiveWorkstructs();/ *切换到第一工作结构* / switchstructpoper(工作1);} / *

模型执行中的算法()函数解除指针变量StructPointer

/* Model step函数*/ 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);}

相关的话题