我和labviewWord文件下载.docx
《我和labviewWord文件下载.docx》由会员分享,可在线阅读,更多相关《我和labviewWord文件下载.docx(137页珍藏版)》请在冰点文库上搜索。
在后面提到的计数器的例子可以验证这一点。
我觉得我说得挺清楚了,出道题目给大家测试一下:
图2:
延时子VI
图3:
计算延时的主VI
图2是一个子VI的代码,功能是延时1000毫秒。
图3是主VI的代码,并行调用同一子VI两次,并计算程序的执行时间。
运行主VI,totaltime的值是多少?
这是可重入VI的一种用途,即希望在不同的线程里同时执行同一个子VI。
另外还有一种情况下,也可以用到可重入VI:
即需要使用到子VI中局部变量保存的数据,而在不同的调用处,这些数据是独立不同的。
这句话可能解释得不那么清楚,看下面例子就会比较容易理解些。
图4:
计数子VI
图5:
测试计数的主VI
图4是一个可重入子VI的代码,功能是计算这个VI被运行的次数,每运行一次,输出的count值就增加1。
图5是调用它的主VI,用于演示这个计数器。
执行主VI一次,output1和output2的值分别是10和20,表示这个子VI在两处分别被调用了10次和20次。
如果把图4中的VI改为不可重入,则output1和output2的输出值是不确定的。
大家可以自己试一试,再想一下原因。
当使用递归结构时,参与了递归调用的VI是需要被同时调用多次的。
因此这些VI中的变量必须是局部的,也就是说参与了递归调用的VI必须都被设置为可重入。
参考:
在LabVIEW中实现VI的递归调用
如何创建和使用LabVIEW中的LLB文件
最近接连有人问我,怎样在LabVIEW中创建一个LLB文件。
于是我就把它写了下来。
通常,需要新建一个文件时,我们很自然就会想到去选中菜单“File->
New”。
可是,在LabVIEW8中,在“新建”菜单中是看不到LLB这种文件类型的;
要创建或者管理一个LLB文件,首先要选择“Tool->
LLBManager...”。
在打开LLBManager之后,再在菜单中选择“File->
NewLLB”。
这样才能创建一个新的LLB文件出来。
我个人认为,在LabVIEW8及以后的版本中,LLB文件现在已经没有存在的必要了,使用它,弊大于利。
LLB文件的功能就是把一组相关的VI以及其他文件打包存储在一起。
其优点是节省磁盘空间,LLB文件是压缩了的。
但是,近年来计算机存储介质的容量迅速膨胀。
LabVIEW程序的存储空间再也不是一个需要考虑的问题了。
所以这方面已经不再有诱惑力了。
LLB文件有很多弊病。
1.内部文件没有层次关系,所有文件都是平级存放的。
这样一来,文件多了,就不能直接看出他们的调用关系。
此外,LLB也允许有同名文件存在。
2.内部文件名长度有限制,大概限制几十个字符吧,文件名太长会被自动截断。
3.不利于版本管理。
LLB中的一个文件被修改,整个LLB也就被修改了。
这样,一是没办法作增量存储,二是不容易定位到具体被改动了的文件上。
综上所诉,如果新建一个工程,最好不要考虑使用LLB文件了。
同时为了方便管理工程中的文件,应当尽量利用LabVIEW8的新功能:
Project和Library。
用户自定义控件中Control,TypeDef.和StrictTypeDef.的区别
为了解释清楚,先定义一下要用到的概念。
我们把以.ctl文件名定义的控件叫做用户自定义控件,把通过拖拽或打开这个.ctl文件在VI上生成的控件叫做实例。
LabVIEW的用户自定义控件包括了三种定义形式:
打开一个.ctl文件,在它上方的“control”下拉条中有三个选择,分别是无关联控件(Control)、类型定义(TypeDef.)或者严格类型定义(StrictTypeDef.)。
无关联控件是指这个控件与它的实例之间没有任何关联。
例如,你制作了一个漂亮的按钮控件保存在.ctl文件中。
需要用到它时,通过拖拽或打开这个.ctl文件就可以在VI中生成这个用户自定义控件的一个实例。
这个实例一旦生成,就和原用户自定义控件无任何关联了。
无论是你修改这个实例,还是修改原用户自定义控件,都不会对另一方产生任何影响。
类型定义控件是指实例控件与用户自定义控件的空间类型是相关联的。
比如,你的用户自定义控件是一个数值型控件,那么它的所有实例控件也都是数值型的。
如果我们在.ctl文件中把用户自定义控件的类型改为字符串,那么它已有的所有实例都将自动变成字符串类型。
有时候,只是类型相关联还不够。
比如对于Ring(Enum,ComboBox)这类的控件来说,如果在用户自定义控件中添加了一项内容(item),一般总是希望它所有的实例也同时添加这一选项。
如果使用类型定义控件,因为控件类型没变,还是Ring,实例们是不会自动跟随更新的。
这时就需要使用严格类型定义控件。
选择严格类型定义后,不但实例与用户自定义控件的类型是相关联的,其他一些控件属性,比如颜色等等,也是相关联的。
使用严格类型定义时有一点容易被误解:
严格类型定义只是与实例控件相关联,由它生成的实例常量的属性是不与之关联的。
实例常量是指通过拖拽或生成常量等方法,在程序框图上生成的一个与.ctl文件相关联的常量。
比如在Ring型用户自定义控件中添加了一项内容,相关的实例常量是不会发生任何改变的。
很多人按常理想,认为常量也应当自动更新,但事实上不行。
这也是我不采用它做常量定义的原因之一。
调整控件和函数面板的首选项
LabVIEW在8.0版对控件和函数面板作了一次较大调整。
LabVIEW功能越来越强大,控件和函数面板上的东西越来越多。
如果增加面板的嵌套深度,用户每次选取面板上的一个控件和函数都要多点几下鼠标,而且对不熟悉位置的东西找起来也相当费劲;
如果扩充每一个面板上的容量,一个面板上图标太多,用户会眼花,也不利于查找。
所以LabVIEW8调整了面板的显示方式:
最顶层面板所有栏目都以文字的方式显示,纵向排成一列。
其中第一个栏目是默认就展开的,可以直接看到次级面板的内容;
其它栏目都收起,鼠标挪上去,才看得到它里面的内容。
我现在用的是
LabVIEW8.2版,它的函数面板看上去是这样的:
(在程序框图的空白处点击鼠标右键)
用鼠标右键弹出函数面板
函数和子VI被分为几大类,每个类的名字被列在弹出的菜单上,其中最前面一个类是展开的。
因为第一个分类中的函数最常用。
但是,有些人可能最常用的函数是在其它分类中的。
这样可以调整一下,比如最常用的是ExpressVI,就可以把它最常用挪到最前面来。
用鼠标点弹出菜单左上角的图钉,就可以吧弹出菜单固定住。
固定后的菜单每一项左端有两个竖线,和一个三角。
点击三角可以展开和收缩这个类里的图标,鼠标放到两个竖线上,鼠标就会变成带箭头的十字花。
这是就可以按下鼠标拖动这个条目了。
点在Express项目的竖线上,然后把它托到最上面。
如图2、图3所示:
图2,3:
鼠标点在连个竖线上可以拖动这个项目
从此以后,Express就在最上面了。
看图4,再在程序框图上点鼠标右键,弹出的函数面板,最上面一栏展开的就已经变成Express了。
新的函数面板
你可能会发现,自己的LabVIEW在鼠标右击程序框图后,只显示出几个分类,其他的类别统统都缩了起来。
用户是可以自己制定显示或隐藏哪些分类的。
在函数或控件面板钉住的状态下(如图2这种状态),点击面板最上方的“View”按钮,就会出现让你更改显示或隐藏分类的菜单。
如果你觉得LabVIEW的面板布局不是很合理,你要用的东西分散在不同的类别里,用哪个坐首选项都不太方便。
那也没有关系,在LabVIEW8.5中又多了一个类别,叫Favorite(我的最爱)。
在函数或控件面板钉住的状态下,右键点击其它类别的函数,或子面板标题,弹出菜单上有一项就是加入到Favorite中。
把你最常用的函数都放到Favorite里去,再把Favorite移到面板的最上端作为首选项,就可以了
在文件夹下直接创建新的VI
在WindowsExplore中,鼠标右键点击某一文件夹的空白处,弹出的菜单中有“新建”一项。
通过修改Windows的注册表,可以给这个新建列表添加一项,从而直接在文件夹下创建一个新的VI。
如图1所示。
在“新建”菜单中添加一项-创建VI
下载CreateNewVI.zip文件,然后解压缩。
运行里面的CreateEmptyVI.reg,把它里面的内容导入到注册表。
然后就会发现多出图1所示的新建VI的项目了。
让Windows多一个新建项目,只要在注册表里添加上相关内容就行了。
CreateEmptyVI.reg文件中的Data数据其实就是新建出来的文件的内容。
在这个例子中,他是一个空白的LabVIEW8.0的VI。
我们可以改变reg文件中的数据,是的产生出来的VI有所不同。
比如,你希望自己的新VI总是使用蓝色背景的,有一个特殊的图标等等,只要改变reg文件中的数据就可以了。
ZIP包中还有一个CreateNewRegData.vi,这个VI可以读入一个文件,把它转换成注册表中实用的Data数据。
使用者可以自己先造一个自己喜欢的VI作为模板,然后利用CreateNewRegData.vi为它创建出一个注册表数据,导入注册表。
这样每次在文件夹下用鼠标右键创建出的VI就是模板VI的样子了。
选择结构
选择结构相当于文本语言中的条件语句。
LabVIEW8中新增加的DiagramDisableStructure,ConditionalDisabledStructure类似C语言中的条件宏定义语句。
一.程序框图禁用结构(DiagramDisableStructure)
在调试程序时常常会用到程序框图禁用结构。
程序框图禁用结构中只有Enabled的一页会在运行时执行,而Disabled页是被禁用、即不会执行的;
并且在运行时,Disable页面里的SubVI不会被调入内存。
所以,被禁用的页面如果有语法错误也不会影响整个程序的运行。
这是一般选择结构(CaseStructure)无法做到的。
图1、2:
使用程序框图禁用结构
例如图1、2中的示例,如果我们在运行程序的时候暂时不希望将test写入到文件里,但又觉得有可能以后会用到。
此时,就可以使用程序框图禁用结构把不需要得程序禁用掉。
需要注意的是程序框图禁用结构可以有多个被禁用的框架,但必须有且只能有一个被使用的框架。
在被使用的框架中,一定要实现正确的逻辑,比如上图的例子中,在被使用的框架中一定要有连线把前后的文件句柄和错误处理联接好。
二.条件禁用结构(ConditionalDisabledStructure)
条件禁用结构则根据用户设定的符号(symbol)的值来决定执行哪一页面上的程序。
其他方面与程序框图禁用结构相同。
程序中所使用的符号,可以在项目或是运行目标机器(例如“MyComputer”)的属性里设置。
条件禁用结构
值得注意的是:
程序框图禁用结构与条件禁用结构都是静态的,如果需要在运行时决定执行哪一部分的程序可以使用选择结构。
程序框图禁用结构和条件禁用结构的一种实用案例可以参考:
《其它常用调试工具和方法》
三.选择结构(CaseStructure)
在一般情况下,选择结构类似于C语言的switch语句。
当输入为bool数据类型或error数据类型时,选择结构类似于C语言中的if语句。
枚举类型的CaseSelector
有输出时,则每一个框架中都必须连一个数据,当然也可以选择“UseDefaultIfUnwired”。
选择“UseDefaultIfUnwired”会有一定的风险,因为你可能会忘记了连线,这时候LabVIEW并不会提醒你,程序就可能得到不可预料的结果。
如图5所示,鼠标右击数据输出隧道,可以选择是否使用“UseDefaultIfUnwired”
选择UseDefaultIfUnwired
顺序结构
一.程序执行顺序
LabVIEW是数据流驱动的编程语言。
程序在执行时按照数据在连线上的流动方向执行。
同时,LabVIEW是自动多线程的编程语言。
如果在程序中有两个并行放置、它们之间没有任何连线的模块,则LabVIEW会把它们放置到不同的线程中,并行执行。
顺序执行和并行执行的例子
顺序执行(图1):
数据会从控制控件流向显示型控件,因此数据流经的顺序为“errorin”控件,“SubVIA”,“SubVIB”,“errorout”控件,这也是这个VI的执行顺序。
并行执行(图2):
“SubVIA”,“SubVIB”没有数据线相互连接,它们会自动被并行执行。
所以这个VI的执行顺序是“SubVIA”,“SubVIB”同时执行,当它们都执行完成以后,再执行“MergeErrors.vi”。
二.顺序结构
如果需要让几个没有互相连线的VI,按照一定的顺序执行,可以使用顺序结构来完成(SequenceStructure)。
MenuPalette
当程序运行到顺序结构时,会按照一个框架接着一个框架的顺序依次执行。
每个框架中的代码全部执行结束,才会再开始执行下一个框架。
把代码放置在不同的框架中就可以保证它们的执行顺序。
LabVIEW有两种顺序结构,分别是层叠式顺序结构(StackedSequenceStructure)、平铺式顺序结构(FlatSequenceStructure)。
这两种顺序结构功能完全相同。
平铺式顺序结构把所有的框架按照从左到右的顺序展开在VI的框图上;
而层叠式顺序结构的每个框架是重叠的,只有一个框架可以直接在VI的框图上显示出来。
在层叠式顺序的不同的框架之间如需要传递数据,需要使用顺序结构局部变量(SequenceLocal)方可。
层叠式顺序结构
三.顺序结构的使用
好的编程风格应尽可能少使用层叠式顺序结构。
层叠式顺序结构的优点是及部分代码重迭在一起,可以减少代码占用的屏幕空间。
但它的缺点也是显而易见的:
因为每次只能看到程序的部分代码,尤其是当使用sequencelocal传递数据时,要搞清楚数据是从哪里传来的或传到哪里去就比较麻烦。
转换顺序结构
使用平铺式顺序结构可以大大提高程序的可读性,但一个编写得好的VI是可以不使用任何顺序结构的。
由于LabVIEW是数据流驱动的编程语言,那么完全可以使用VI间连线来保证程序的运行顺序。
对于原本没有可连线的LabVIEW自带函数,比如延时函数,也可以为其包装一个VI,并使用errorin,errorout,这样就可以为使用它的VI提供连线,以保证运行顺序。
图6:
改进的延时VI
定时结构
定时结构是从LabVIEW7.1开始出现的。
一眼就能看出来,它在外观与其它结构的风格完全不同。
倒是和LabVIEW7力推的ExpressVI,风格一致。
打开定时结构的函数面板(图1),最上面两个分别是定时循环,和定时顺序结构。
下面的是与控制时间结构相关的的一些VI。
时间结构的函数面板
定时结构,顾名思义,与时间控制有关。
LabVIEW中原本有一些用于延时或定时的函数,比如Wait,DelayTime等,他们都位于Time&
Dialog面板中。
利用这些函数,基本可以实现与使用时间结构相同的功能。
定时结构的最大改进在于,它可以选择使用哪个时间源(硬件)来定时。
尤其是当你的LabVIEW程序运行在RT、FPGA等设备上时,这一点就特别有用了。
使用定时结构指定使用硬件设备上,而不是PC机上的时钟来定时,可以使使运行时序更精准。
即便同样都是在普通PC上使用,定时间结构的定时效果也要比
Wait等函数精确的多。
我曾经参与过的一个测试程序,开始使用Wait函数定时,运行一小时后,时间误差有几分钟。
改用定时结构后,误差缩短到了几秒钟。
缓存重用结构
一、缓存重用
在《LabVIEW程序的内存优化》一文中有一个利用移位寄存器来降低VI内存的例子。
下面这个VI大约会占用了2.7M的内存空间
对数组进行数值运算的顺序执行程序
给它加上一个移位寄存器,如下图所示,内存占用就降低到只有不到400k了。
利用移位寄存器实现缓存重用
这其实是利用了移位寄存器两端接线端指向的是同一块内存这一特性,主动的告诉LabVIEW这段代码上的每个加法节点的输入输出数据可以使用同一块内存。
避免的LabVIEW分配不必要的数据缓存。
但是代码还是不够完美,本来不需要循环,却非得摆上一个只执行一次的循环结构。
感觉上总是有些别扭。
这个问题终于在LabVIEW8.5中被解决了。
LabVIEW8.5中多出了一个结构——缓存重用结构,专门用于告诉LabVIEW在某段代码上为输入输出数据做缓存重用。
上面这个程序用新的缓存重用结构来写就是这样的:
利用缓存重用结构实现缓存重用
二、使用缓存重用结构
缓存重用结构与其它结构不在同一个函数选板上。
这是缓存重用结构不是一个功能性、或改变程序流程的结构。
它的使用不会改变代码的功能,仅仅会改变代码的效率。
要使用缓存重用结构,需要打开函数选板的Programming->
ApplicationControl->
MemoryControl。
第一个选项就是他了。
缓存重用结构在函数选板上的位置
缓存重用结构为了方便使用,并不是简单的作为循环加移位寄存器的替换,它还有一些可选的边框节点,帮助编程者处理不同的数据类型。
刚刚被拖到程序框图上的是一个光滑的黄色方框,要使用它的缓存重用功能还要为打算从用的内存,根据它的数据类型选择相应的边框节点。
在黄色的边框上点击鼠标右键,弹出菜单的最后几项就是可供选择的边框节点类型。
如图5所示。
每种边框节点都是成对出现的,一个在输入端,另一个在输出端。
添加边框节点
三、边框节点
1.数组元素索引和替换节点
这对节点用于改变数组中某个元素的值。
输入的数组数据连到缓存重用结构左面的数据索引节点上,结构内得到的数据,就是需要处理的元素的数值。
LabVIEW中使用递归调用不是很方便。
不过递归并不是编程必须程序结构,任何需要使用递归调用的地方,都可以用循环结构来代替。
但是在某些情况下,使用递归调用的确可以大大简化程序代码,对缩短编程时间、提高程序可读性都非常有帮助,所以学习一下递归的实现方法还是有好处的。
一、为什么VI不能够被静态的递归调用
LabVIEW不能通过静态调用的方法(把子VI直接放到另一VI的程序框图上)来实现递归。
对于一个非可重入的subVI,在每一个时间,这个subVI这能被运行一次。
LabVIEW需要借此来保证多线程时的数据安全。
对于被递归调用的代码,是需要在它执行到中间的时候,就再次被调用的。
所以默认设置下的VI不能被静态递归调用。
对于被设置为可重入的VI,是可以被同时调用多次的,但也不能被静态的递归调用。
除非是通过VI
Server动态的调用VI,否则,LabVIEW是在一个程序被调入内存,开始运行之前就为它的所有VI分配好内存空间的,包括数据区。
如果一个VI不是可重入的,LabVIEW会在这个VI运行时局部变量所在的数据区开辟在这个VI所在的空间内;
对于可重入的VI,LabVIEW把它的数据区开辟在调用者VI上,这样就可以保证这个可重入VI在不同的地方被同时调用时使用不同的数据区,以防止多线程运行时数据混乱。
因此,可重入VI虽然可以被同时多次调用,但是被调用的次数是运行前就确定的。
而递归运算时的调用次数是运行时决定的。
这样,如果是静态调用,LabVIEW根本没有办法为提前为参与递归的VI开辟好数据区。
二、用动态调用方法实现递归