Skip to main content

编写更复杂的程序

我们在 “Hello,World! 程序” 一节中创建了自己的第一个 VI,但是它过于简陋。接下来,我们将对它做一点改进,同时介绍 LabVIEW 的其它一些基本用法。了解了这些用法,才算是 LabVIEW 入门了。

美化 VI

添加图标

首先,要养成一个好习惯,就是要为每个编写好的 VI 都设置一个漂亮的、有意义的图标。

图标是 VI 前面板或程序框图窗口右上方的那个正方形图案,它是一个 32×32 像素点的 256 色图片(图 1.22)。

图 1.22 箭头所指为 VI 的图标

图标是 LabVIEW 特有的一个优势。与 LabVIEW 相比,文本编程语言不需要,也不可能为每一个编写出来的函数设置图标。人脑对图像的处理速度要比处理同样信息量的文字快得多。因此,阅读一个编写风格良好的 LabVIEW 代码要比阅读一个文本程序的代码更容易、更快速。比如图 1.23 中这个 VI,一看就知道它和生成波形有关。

\ 图 1.23 一个 VI 的图标

VI 的图标虽然会给这个 VI 的使用者带来方便,但却需要它的编写者花费一定的时间与心思来设计绘制它。LabVIEW 2009 版对图标编辑器做了较大的改进:旧版本 LabVIEW 的图标编辑器非常简洁,但功能有限;LabVIEW 2009 为图标的编辑器增添了绘图工具中常用的功能,来帮助开发人员快速制作精美的 VI 图标。下文着重介绍一下 LabVIEW 2009 之后的新图标编辑器

在 VI 的前面板或程序框图窗口上,用鼠标双击图标,即可打开图标编辑器(图 1.24)。在打开的图标编辑器上可以看到,它拥有多个选项卡页面。每个页面从不同的角度帮助开发者对图标进行加工制作。

第一个页面是模板页。开发者在设计 VI 的图标时,往往会预先考虑让功能相关的一批子 VI 具有有共同的风格,比如说共同形式的边框、底色、标签、装饰图案等。 绝大部分公司企业也会为自己开发的 VI 制定规范,统一图标风格。这些共同的部分,可以作为模板保存起来。编辑新图标时,先从模板中选取一个模板图标,然后再在其基础上修改,可以提高工作效率。

对于一个新创建的 VI,清空 LabVIEW 默认设置的图标,点击一下已有的模板,这个模板就被复制到新 VI 的图标上了。

\ 图 1.24 图标编辑器的 "模板" 页

对于 LabVIEW 2009 的新图标编辑器,可以使用图标右侧的编辑工具直接在图标上输入文字。不过,在 "图标文字" 选项页中已经提供了更便捷的添加文字方法。可以在这一页面提供的文本框中,直接输入想要写的文字。图标编辑器提供了四行文字输入框,每行文字可以使用不同的颜色,选择不同的字体与大小。若新图标编辑器写出的文字在图标上模糊不清,那是因为字体不够大引起的。调整一下这个页面上的字号选项,就可以让文字变清晰了。

既然是本书介绍的第一个 VI,就用一个数字 "1" 来作为它的图标吧。

\ 图 1.25 "图标文本" 页

对于很多人来说,选取图形大概是图标编辑器中最有用的部分了。VI 开发者最头疼的就是如何绘制即能体现程序功能、又简明好看的图标。如果能从现成的库里选取几个图形,组成一个合适的图标,那肯定是开发者的心愿。"符号" 选项页就提供了大量候选的小图片元素,可以直接把它们拖到右侧图标框上。

\ 图 1.26 图标编辑器的 "符号" 页

图标编辑器中制作的图标是有图层的。图标中的模板背景、文字、图形元素等,都被保存在了独立的图层中。有了图层,就可以只针对图标中某一图层进行修改,而不影响其它图层上的内容。比如将这一图层上的图形挪动一下位置、设置为半透明等。

\ 图 1.26 图标编辑器的 "图层" 页

图标编辑器还有一个额外的优点:它是开源的 LabVIEW 代码程序,它的主 VI 位于 "[labview]\resource\plugins\lv_icon.vi"。 如果想参考一下这个复杂程序是如何编写的,打开来就可以看到源代码了。

尽管 LabVIEW 2009 的图标编辑器在功能上改进了不少,但早期版本的图标编辑器(图 1.27 所示)也具有一定的优点。比如,新图标编辑器启动速度慢、无法书写清晰的小字号文字、运行不稳定等。旧版本的图标编辑器并没有从新版本的 LabVIEW 中移除,用户仍然还可以使用它:给 "[labview]\resource\plugins\lv_icon.vi" 改个名字,再打开图标编辑器时,LabVIEW 找不到新的编辑器,就会自动打开旧版本的那个。

图 1.27 LabVIEW 2009 版之前的图标编辑器

在设计图标时,只在图标上写几个字,虽然可以不必费劲心思去设计图形了,但也丧失了其图形化的优势。虽然上文的示例中只在图标上写了一个 "1" 字,但读者在编写正规的程序时,还是应当尽量为每个 VI 设计一个简单明了,又有意义的图标。

设置字体

我们这个 VI 的前面板上只有一个字符串显示控件,而且仅仅显示几个文字(图 1.10),我们可以把显示出来的文字字体调大,使它看起来更清楚。用鼠标选中字符串显示控件中的文字,然后点击窗口工具条上的文本设置按钮!,可以把文字的字号改大。读者还可以试着做些其它改动(如字体、字型、色彩等),使界面看起来更加赏心悦目。

设置标题

为了让 VI 界面显示得更为专业,还可以改变 VI 窗口上默认的标题。选择菜单中的 "文件 ->VI 属性",或者鼠标右击 VI 图标,选择 "VI 属性",调出 VI 属性对话框(图 1.24),在对话框中选择 "窗口外观" 类别,然后就可以修改窗口标题了。VI 属性对话框中有很多设置,读者可以自行尝试一下其用途,在本书后面的章节中也将会提及其中一些主要的设置。

图 .24 VI 属性对话框

经过我们修改的 VI 运行后,外观看起来舒服多了(图 1.25)。

图 .25 经过改善的 VI 界面

"您吃了吗?" 这个程序还有其它的实现方法。比如,可以让这段文字显示在一个弹出对话框窗口上。使用 "单按钮对话框" 函数即可达到这个效果(图 1.26)。(单按钮对话框位于 "编程 -> 对话框与用户界面" 函数子选板上。)

图 .26 使用单按钮对话框函数

让 VI 持续运行

我们前面编写的程序属于那种一按运行按钮,程序马上运行,得到所需的结果后立即停止的。但是,我们还经常需要编写那些要求能够持续运行一段时间的程序。例如,编写一个检测程序,要求程序一直监视被测对象,若测量值发生变化,程序立即处理新的数据并显示出来。

下面以一个简单的程序为例,介绍让程序持续运行的方法。图 1.27 和图 1.28 是一个简单的加法程序,它的功能是用 "量表" 控件来显示 "旋钮" 和 "转盘" 数据的和。程序运行一次,就会立即得到结果。但是,我们还希望它能够持续运行,这样用户就可以随时调整 "旋钮" 和 "转盘" 数值,而 "量表" 也可以立即显示出新的计算结果。

图 .27 加法运算的前面板

图 .28 加法运算的程序框图

实现此功能最简单的办法,就是点击工具条上的 "连续运行" 按钮!。点击此按钮后,程序在得到运算结果后不会停止,而是立刻重新运行,直到点击 "终止运行" 按钮! 为止。此时,调整 "旋钮" 和 "转盘" 的数值,"量表" 中的数值会立刻随之变化。

但是,这个连续运行的方案有其不足之处,它只在临时调试时使用。因为通常提供给最终用户的是 VI 生成的可执行文件,它是没有 "连续运行" 按钮的。并且,使用 "连续运行" 按钮,程序内所有的代码都会反复运行,没办法将程序中只需运行一次的代码和需要重复运行的代码区分开来。

持续运行的真正有效方案是使用循环结构。在函数选板中选择 "编程 -> 结构 ->While 循环",把循环结构拖到 VI 的程序框图上,再把加法运算的整个代码都置于循环体内。while 循环看上去是一个深色的矩形方块,方块包围的区域称为循环体。while 循环的含义是:若不满足循环停止条件(或者满足循环继续运行条件),程序将持续重复执行循环体内的代码。(本书会在 循环结构 一节中对 while 循环做详细阐述。)

while 循环的矩形框内,右下角的红色小块用来输入循环条件。鼠标右键点击在循环条件上,在右键菜单中选择 "创建输入控件",就可以为循环条件创建一个控制按钮(名为 "停止")。当点击这个按钮的时候,循环就停止运行。

现在再点击工具条上的 "运行" 按钮,程序将持续运行,与前文提到的点击 "连续运行" 按钮起到的效果是相同的。点击 VI 前面板上的 "停止" 控件,可以使 VI 运行停止。

但是,这个程序还需要再改进。因为这个程序在运行时,短时间内循环就可以达到非常高的迭代次数:每秒钟循环迭代可达一千万次以上(与电脑硬件配置有关),它占用了大量 CPU 资源。实际上,运算的更新速度不需要那么快。"转盘" 数值的更新速度如果超过每秒三、四次,人眼就已经跟不上其变化了。因此,我们可以通过延时来降低循环的迭代频率。把函数选板中的 "编程 -> 定时 -> 等待" 函数添加到循环体内,并设置等待时间为 200 毫秒。这样,循环体内的加法计算结束后,需要等待大约 200 毫秒,才能结束本次循环,进入下一轮循环。如此改进后,程序对 CPU 的占用率只有原来的几百万分之一,可以有效降低程序对 CPU 资源的浪费。改进后的程序框图如图 1.29 所示。

图 .29 持续运行的加法计算

项目

要实现更复杂的功能,单个 VI 就不够用了。稍微复杂一点的程序都由多个 VI 组成,大型的应用程序可能会有成千上万个 VI。对于数量众多的 VI 而言,需要一个行之有效的方法进行管理。从 8.0 开始,LabVIEW 增加了一个名为 "项目浏览器" 的功能。LabVIEW 项目浏览器是一个可以方便地查看、调整程序系统结构的工作区,它与 VC、VB 等语言中的 project、workspace 类似。

项目浏览器的出现使得 LabVIEW 对于项目的管理更加方便,所以我们以后再创建新的程序时,都应该从建立新的项目开始。在 LabVIEW 起始界面中选择 "新建 -> 项目",可以创建一个新的项目(图 1.30)。然后再根据需要在项目中创建、添加新的 VI 以及其它文件设置等。

图 .30 项目浏览器

项目浏览器用一个树形的结构来表示项目中所有的 VI 和其他文件设置等组成。

树形结构的最顶层是项目的名称。

第二层是项目运行的目标机器。假如计算机上只安装了一份普通台式机版的 LabVIEW,在这一层就只能看到一个目标机器:"我的电脑";如果计算机上还安装了 LabVIEW RT、FPGA 等其它硬件环境下运行的 LabVIEW,那么在这一层就能够看到那些已经安装了的其余的目标设备。

第三层以下就是项目中所有使用到的文件了。用户可以添加虚拟文件夹,按自己的喜好组织文件结构。从 LabVIEW 8.0 开始,文件种类一下子丰富起来了。以前基本上只有 VI 和控件两种文件,现在又增加了 Library、Class、XControl 等文件类型。(在本书随后的章节中将会介绍这些文件的功能和应用。)如果安装了某些 LabVIEW 工具包,文件种类还会更多一些。右击树状结构中的每个条目,可看到针对他们的更多设置。

如果需要,也可以把先前已经创建好的 VI 添加到项目中:鼠标右键点击 "我的电脑",在菜单中选择添加,可以把我们之前编写的 VI 都添加到项目中来。

使用子 VI

若一个 VI 应用于其它 VI 中,就称其为子 VI。子 VI 相当于文本编程语言中的子函数。

一个功能十分复杂的 VI,其程序框图上会有大量节点和连线,甚至于电脑屏幕都无法一次完整地显示出其全部代码。这种复杂的框图,难以阅读和理解。为此,通常需要把复杂的程序划分成若干小的程序模块,每个模块只完成简单功能。每个程序模块由一个 VI 来实现,这个 VI 的程序框图上只需少量节点和连线,读者可以很容易、快速地读懂这个简单功能的 VI。最终由一个主 VI 调用这些简单功能的子 VI,以实现其所有的复杂功能。由于主 VI 的程序框图仅由数个子 VI 组成,也是比较容易理解的。这样整个程序的可读性都得到了提高。

图 1.31 是一个比较复杂的主 VI 程序框图,尽管没有什么注释,但仅从子 VI 的图标也可以大致了解到这个程序完成的是:打开一个硬件设备,对其进行一定的设置,然后读取数据,再关闭该硬件设备。可以想象,这个程序如果不是用子 VI 表示,而是把所有的程序都罗列在一个 VI 的程序框图上,那肯定是很难读懂的。

图 .31 使用了子 VI 的程序框图

图 1.32 是作者故意编写的一个作为反例的 VI。它的程序框图没有合理划分和使用子,以至于程序框图极为庞大复杂,恐怕任何一个人都不太容易弄懂这一段程序的含义。而屏幕上显示出来的代码只是这个 VI 程序框图很小的一个角落。遇到这种大型的程序框图,可以选择菜单中的 "查看 -> 导航窗口",在导航窗口中查看整个代码框图的缩略图。图 1.32 右下方的灰色浮动窗口就是导航窗口。

图 .32 作者故意编写的用作反例的 VI

有过文本编程语言经验的读者,可能会倾向于只有在需要重用某一段代码时,才把这段代码做成子函数。在 LabVIEW 中却并非如此。LabVIEW 程序中的大多数子 VI 的存在并不是为了代码重用,而是为了提高代码的可读性和可维护性。一个理想的项目的 VI 层次结构应当是金字塔型的:打开 VI 层次结构窗口(在项目主 VI 的菜单中选择 "查看 ->VI 层次结构"),可以看到,主 VI 调用了数个子 VI,第二层的每个子 VI 又分别调用第三层的数个子 VI,依次层层调用(图 1.33)。这样层次分明、又没有交叉调用的程序结构是最容易阅读和理解的。

图 .33 某一项目的 VI 层次结构

创建子 VI

创建子 VI 与创建普通 VI 的起始过程是相同的:设计 VI 的前面板,编写程序框图,编辑图标,保存。但是,子 VI 要被其它 VI 调用,所以还需要特别设置子 VI 的输入输出参数。

子 VI 前面板上的控制控件均可以作为输入参数,而显示控件则可以作为输出参数。但是要注意,控件只有在与 VI 的连线板相连后,才能作为输入输出参数。

例如,我们编写一个简单的子 VI,用于把输入的以华氏度为单位的温度值转换为以摄氏度为单位的温度值。这个 VI 的输入和输出分别是一个实数类型的数值。先编写好它的前面板和程序框图,然后,就要把 "华氏温度" 设为 VI 的输入参数,而把 "摄氏温度" 设为 VI 的输出参数(图 1.34)。

图 .34 华氏转摄氏 VI 的前面板和程序框图

在 VI 前面板的图标处,单击鼠标右键,选择菜单中的 "显示连线板"。原来显示图标的位置,就变成了由小矩形组成的正方型图案:。这些小矩形被称为 "接线端"。默认的连线板从左到右均分成四列,每一列矩形的数量分别是 4,2,2,4。我们按照每一列矩形的数量来命名连线板模式,例如,默认的连线板模式是 4224 模式。在连线板右键菜单的 "模式" 栏中,还可以选择其它的模式,但是大家可以记住一个简单的原则:为了让自己编写的代码更美观,凡是能用 4224 模式的子 VI 连线板,尽量使用 4224 模式。

连线板中每一个接线端可以和一个控件相连。LabVIEW 程序中数据的流动方向通常都是从左到右,习惯上输入在左边,输出在右边。因此,连接连线板的时候也要遵循这个原则,尽量保持连线板左侧的接线端与控制控件相连,而右侧的接线端与显示控件相连。

连接连线板时,首先用鼠标点击一下连线板的某个接线端,然后再在与其相对应的控件上点击一下,控件与连线板就关联好了。与控件相连后的接线端颜色会发生变化,以提示编程者注意,避免错误的连接。接线端显示的颜色与连接该控件的连线的颜色是一致的,以方便编程者区分。连接好的连线板如图 1.35 所示。

图 .35 连接好连线板的 VI

图 .36 使用子 VI

在主 VI 中,调用子 VI 的方式与调用函数类似,可以有多种途径。最简单的方式是将鼠标移动到子 VI 的图标处,按住鼠标左键直接将图标拖拽到上层 VI 程序框图上即可。在子 VI 已经保存关闭后,也可以在主 VI 的程序框图中打开函数选板,选择 "选择一个 VI" 项,在弹出的选择框中选择相应的子 VI,将其放置到主 VI 的程序框图上。图 1.36 是一个使用了子 VI 的程序框图。

在主 VI 的程序框图中,鼠标移到某个子 VI 的图标上,该子 VI 的接线端就会显示出来,帮助对其进行连线。

从程序框图创建子 VI

在编写 VI 时,经常是 VI 的程序框图越写越大,这才意识到,需要把它拆分成子 VI 以降低单个程序框图的复杂度。这种情况下,也可以直接在 VI 程序框图上选出其中的一部分,直接创建成子 VI。

图 1.37 是一个较大程序框图的一部分。它上面显示出来的被鼠标选中的部分(被虚线包络的部分)代码相对比较独立,可以创建成子 VI。用鼠标选中这部分代码,然后在菜单中选择 "编辑 -> 创建子 VI",这部分代码就会被一个新创建的子 VI 代替,子 VI 中的代码就是刚才用鼠标选中的那部分。

图 .37 选中程序框图中的一部分代码

图 .38 一部分代码变成子 VI 后的程序

从程序框图创建子 VI 时,需要注意以下两点。首先,只有相对比较独立的代码部分(与程序框图的其它部分连线较少)才适合分离出来做成子 VI。其次,生成的子 VI 使用的是默认的图标和连线板模式,此时需要立即打开新创建的子 VI,编辑图标和连线板,然后保存。

练习

  • 创建一个新的 VI,再为 VI 画一个漂亮的图标。