LabVIEW虚拟仪器项目开发与实践
上QQ阅读APP看书,第一时间看更新

3.7 数组、簇和矩阵

数组(Array)和簇(Cluster)是LabVIEW中对数据进行封装的基本方式。数组用来封装同类型的数据,簇则用来封装不同类型的数据。如前所述,字符串可以被看作是特殊类型的数组,它将一串顺序排列的ASCII字符封装在一起。图3-24是LabVIEW中数组和簇的操作函数集。

图3-24 LabVIEW中数组和簇的操作函数集

数组由数组元素(Elements)和维数(Dimensions)组成。数组元素是组建数组的数据,维数用于说明数组的长度、高度和深度。数组维数可以是一维或多维,如果内存允许,数组每一维的元素可以多达231–1个。例如图3-25(a)显示了由一路信号的9个数据采集点组成的一维数组,其中每个数据元素均对应一个索引;图3-25(b)显示了每一路9个数据采集点的三路信号组成的二维数组。二维数组的组织方式类似于表格,其中每一行和每一列均相当于一个一维数组。二维数组中数据的定位需要同时使用行索引和列索引。三维数组组织方式类似于立方体,其中每一页相当一个二维数组,三维数组元素的定位需要行、列和页面三个索引。

图3-25 一维数组和二维数组示例

设计人员可以创建包含各种类型元素的数组。数组元素既可以是数值、布尔、枚举和字符串等基本类型,也可以是路径、波形、簇甚至类对象等特殊类型。然而设计人员不能创建元素为数组的元素,这是因为它在本质上与多维数组相同。如果非要体现类似的意义,可以创建元素为簇的数组,其中每个簇包含一个或多个数组。此外,在LabVIEW中也不能创建元素为子面板(Subpanel)、Tab、.NET控件、ActiveX控件、图表(Charts)或XY图(Graphs)的数组。

从对数据封装的角度来看,数组就如同是连续存放同类型数据的容器。这种容器可以在对同类型数据进行重复计算或处理时使用。当程序中每个循环产生一个数组元素或进行数据采集时,使用数组会非常理想。要在数组中定位某个特定元素,需要使用每一维数组的数据索引(Index)。数组每一维索引的起始值均为0,并按顺序递增。也就是说索引为0的元素为第一个元素或维数,1为第二个,2代表第三个,直到N-1(N为数组元素的总数)。通过数组索引,可以遍历数组的任意元素、行、列以及多维数组的数据页。

簇和C语言中的struct类似,用来封装不同类型的数据。例如LabVIEW中传递错误信息的簇(Error Cluster)就封装了布尔类型、数值和字符串类型的数据。一个簇在后面板上对应一个端子,将多个类型不同但却逻辑相关的数据封装成一个簇后就可以减少后面板上连线的数量,使代码更整洁。另外,如果将簇作为子VI的输入或输出,由于每次可以传递多个数据,因此可以极大地减少对子VI输入/输出端子数量的需求。LabVIEW中每个子VI最多允许连接28个输入/输出端子,但如果配合上簇的封装能力,如果不考虑内存限制,理论上可实现无穷多个数据到子VI的传递。

设计时在前面板创建簇的方法和创建数组的方法类似,也是先将簇的壳拖放至前面板,然后在其中添加数据元素。在簇中不能同时存在控件和显示控件。例如第一个被放入簇中的控件为控件属性,如果后续拖放入簇中的元素属性为显示控件,则系统会按照第一个被拖放入簇中的控件属性自动改变后续控件的属性,以使所有簇中元素属性相同。每个被封装在簇中的数据元素均有一个逻辑编号,这个编号和它在簇中的位置无关,而与在创建簇时数据元素被放入簇中的先后顺序有关,这里所说的“放入”不仅指在前面板设计时在簇中手动放入元素的过程,也指运行时通过代码创建簇时元素的顺序。第一个被放入簇中的元素编号为0,第二个被放入簇中的元素编号为1,以此类推。如果向簇中增加或从簇中删除数据元素,系统会自动维护簇中数据元素的编号。如果出于某种原因需要手动改变簇中元素编号顺序,则可以通过选择簇对象的右键菜单中的“重新对簇控件排序”(Reorder Controls In Cluster)选项来修改簇中元素的编号。

程序运行时,有两种方法可以将不同类型元素捆绑(Bundle)成簇或从簇中解除捆绑(Unbundle),一种是按编号进行捆绑或解除捆绑,另一种是按名称进行捆绑或解除捆绑。LabVIEW提供了对应于这些方法的函数,使用这些函数可以在程序中进行下列操作:

(1)用“按编号捆绑函数”(Bundle)在代码中创建簇。

(2)用“按名称捆绑函数”(Bundle by Name)对已有簇中元素进行修改。

(3)用“按编号解除捆绑函数”(Unbundle)分解出所有簇中元素。

(4)用“按名称解除捆绑函数”(Unbundle by Name)分解出簇中某个或部分元素。

按编号进行捆绑或解除捆绑时,必须指明用于创建簇的所有元素,而按名称进行操作时,可以只对某一个或部分元素进行捆绑或解除捆绑,但它仅用于对已有簇进行修改、访问,同时要求簇中的每个元素都必须有一个唯一的标签。例如,可以通过代码将某被测件(Device Under Test, DUT)的类型、高度和长度信息捆绑成簇,在程序中使用解除捆绑簇来获得DUT的类型、高度或长度信息。

图3-26给出了一个简单的示例,开始时先将高度为10、长度为20的TypeA类型DUT信息按编号封装成簇,此时必须同时提供所有簇元素信息。其次,按照名称仅将捆绑成簇中的DUT类型信息解除捆绑并显示出来,同时使用按名称捆绑将开始时捆绑好的簇中的DUT类型和高度信息进行了更新。注意在使用按名称捆绑和解除捆绑时并不要求同时提供所有簇元素的信息。最后使用按编号解除捆绑的方法将更新后的簇元素信息全部分解出来,由于使用了按编号解除捆绑的方法,因此必须同时将所有元素分解出来。由上可见虽然簇和数组的元素均按顺序编号,但是访问数组元素和访问簇元素的方法却不同。

LabVIEW包含一个被称为错误簇的特殊簇结构,它包含以下一些元素:

(1)错误状态:布尔值,错误产生时报告TRUE。

(2)错误代码:32位有符号整数,以数值方式识别错误。

(3)错误源:用于识别错误发生位置的字符串。

图3-26 簇捆绑和解除捆绑函数的使用

错误簇通常用于在程序中传递错误信息。图3-27(a)是错误簇在前面板的显示,图3-27(b)是典型的带错误处理的子VI代码结构。

图3-27 错误簇的使用

虽然簇操作看起来简单,但是在设计过程却被广泛应用。因为它是创建用户自定义数据类型的有效手段,同时利用它将数据进行封装后可以显著地减少后面板连线的数量,同时有利于数据在VI之间的传递。最典型的例子就是在面向对象的程序设计中,类的私有数据均被封装在簇中,而在程序中对私有数据的访问通过公有的数据访问函数来实现。而在这些数据访问函数中,私有数据正是通过以上所讲的按名称捆绑和解除捆绑方法实现的。第11章对此将作详细介绍。

矩阵(Matrix)通常替换多维数组来参与算数运算。对于矩阵运算(尤其是一些线性代数运算),由于矩阵数据类型可以存储实数或复数标量的行或列,因此在矩阵运算中应尽量使用矩阵数据类型,而不是使用二维数组表示矩阵数据。从这一点来看,矩阵数据类型使数学建模更简单。

执行矩阵运算的数学VI接收矩阵数据类型并返回矩阵结果,这样数据流后续的VI和函数就可执行特定的矩阵运算。如果不执行矩阵运算的数学VI可以支持矩阵数据类型,则该VI会自动将矩阵数据类型转换为二维数组。如将二维数组连接至默认为执行矩阵运算的VI,根据二维数组的数据类型,该VI会自动将二维数组转换为实数或复数矩阵。由于LabVIEW保存矩阵和二维数组的方式相同,这种数据转换并不会影响整体性能。

大多数数值函数支持矩阵数据类型和矩阵运算。例如,乘函数可将一个矩阵与另一个矩阵或数字相乘。通过基本数值数据类型和复数线性代数函数,可创建执行精确矩阵运算的数值算法。