结构体变量建模之终极解决方案—上篇中提到:
C 代码中的结构体变量跟模型中的 Bus 信号是对应的;
C 代码中的结构体类型跟模型中的 Bus 对象相对应。
下面我们来看看结构体数组。
三. 结构体数组的代码实现
从前面结构体变量和结构体嵌套的两个例子,我们也可以很清楚的体会到这两点。所以,结构体数组,对应到模型中,自然也就是多维的 Bus 信号了。
对图中 Inport 端口的 Data type 设置为 Bus: myBus,Port dimensions 设置为 2;数据字典中和信号 x 对应的信号对象 x 做同样的设置,即 Datatype为Bus: myBus,Dimensions 为2。Selector 模块分别选中两维信号的第一维和第二维。两组信号经过运算之后,再次通过 Bus Creator 模块组合成 Bus 信号,再把两路 Bus 信号使用 Vector Concatenate 模块连成维数为 2 的 Bus 信号 y。
信号对象 x、y 除了数据类型设置为 Bus: myBus 之外,Storage Class 均设置为 ExportedGlobal。
由此,就有了如下结构体类型的定义:
typedef struct
{
real_T a;
real_T b;
real_T c;
} myBus;
和结构体数组的定义:
myBus x[2];
myBus y[2];
或许你已经注意到几个增益模块的参数值被设置为 k.a,k.b,k.c,没错,既然 myBus 作为结构体类型是一种组合数据类型,同样也可以使用这个 myBus 设置参数 k 的数据类型,只是,一旦参数对象 k 的数据类型被设置为 myBus,那么参数的初始化就不像以前那么简单的。本例设置如下:
k.Value = struct(‘a’,2, ‘b’,3, ‘c’,4);
如果参数k的存储类设置为 ConstVolatile,那么代码中参数 k 的定义如下:
const volatilemyBus k =
{
2.0,
3.0,
4.0
};
四. For-Each和结构体数组的结合
上例中 Bus 信号的维数为 2,所以我们很轻松的使用了 Selector 模块,把两维数据分别取出来实现后续算法,而现实中,我们可能面临几十甚至上百维的 Bus 信号,而后续的处理算法,对于每一维来讲都是一致的,这种情况下怎么办?我们可以想象得见,代码中是可以通过一个 For 循环去实现的,模型当然也可以,这就是 For-Each 子系统。
双击上图中的 For-Each 子系统,得到下图:
这个模型中 Inport 和 x、y 信号对象的 Dimensions 为 100。生成代码之后,除了 x、y 两个结构体数组的维数变成 100 之外,算法中有如下代码:
结合 For-Each 模块,让我们的结构体数组建模更为方便。本想就此结束本篇,想到还会有人惦记另外一些结构体相关的话题,就再说一说:
五. 位域结构体的代码实现
Simulink 参数对象和信号对象的存储类(Storage Class)里面都有 BitField (Custom) 选项,必须要说明的是,如果你的数据类型设置为 boolean,并且存储类选择为 BitField,是可以生成位域结构体变量的,只是,正如上一篇微文有网友留言所说,这样做没法指定结构体元素的顺序,当然也没有 Bus 与之对应。
如果我们想得到我们期望的结构体变量,比如:
typedef struct
{
unsigned char a:1;
unsigned char a1:1 ;
unsigned char a2:1;
unsigned char a3:1;
unsigned char a4:1;
unsigned char a5:1;
unsigned char a6:2;
}myBitFieldBus;
或者:此结构体类型中,前 6 个元素各占 1 个 bit,而第 7 个元素占 2 个 bit。模型如下:
显然,Inport 端口的数据类型应该为 myBitFieldBus,信号对象 input 也一样。
数据字典中定义了 myBitFieldBus 如下:
不难看出:
myBitFieldBus 内的元素 a,a1,a2,a3,a4,a5,均为 boolean 类型,a6 为 uint8;
Bus 对象 myBitFieldBus 的 Data scope 为 Imported,并且定义在头文件。
mybitfieldstruct.h 文件中,也就是说,结构体类型 myBitFieldBus 不在这个模块中定义,为了能够生成代码,需要提供 mybitfieldstruct.h 文件。
做完上述设置之后,生成代码,如下:
typedef struct
{
boolean_T Out1;
boolean_T Out2;
boolean_T Out3;
boolean_T Out4;
boolean_T Out5;
boolean_T Out6;
unit8_T Out7;
} ExtY_bitfieldstruct_T;
myBitFieldBus input;
xtY_bitfieldstruct_T bitfieldstruct_Y;
void bitfieldstruct_step(void)
{
bitfieldstruct_Y.Out1 = input.a;
bitfieldstruct_Y.Out1 = input.a1;
bitfieldstruct_Y.Out1 = input.a2;
bitfieldstruct_Y.Out1 = input.a3;
bitfieldstruct_Y.Out1 = input.a4;
bitfieldstruct_Y.Out1 = input.a5;
bitfieldstruct_Y.Out1 = input.a6;
}
还要什么?指向结构体变量的指针?那就把前面几个例子里的 x、y、input 等信号对象的存储类设置为 ImportedExternPointer 就可以了,没什么特别的。
最后:
C 代码中的结构体变量跟模型中的 Bus 信号是对应的;
C 代码中的结构体类型跟模型中的 Bus 对象相对应。
全部0条评论
快来发表一下你的评论吧 !