LabVIEW

 找回密码
 注册
查看: 389|回复: 2

[共享贴] LabVIEW动态调用VI的作用和实现细节

[复制链接]
发表于 2021-10-29 11:20:43 | 显示全部楼层 |阅读模式
USB-6009数据采集卡首发
为了说明状态机、动态调用的作用和动态调用的注意事项,设计如下小程序
首先从Excel文件中读取100个数,面板有两个按钮,一个可以将这100个数求和,另一个将每个数加1. 之所以设计这个看起来没什么用的程序,是因为逻辑上以及架构上和最近做的一个实际项目很接近,只是功能简化了很多,此外还有以下几个原因
) z3 {2 q* h! G1 i) v
  • 动态调用VI的目的是为了优化内存,不过小程序不容易看出内存优化的状况。初始化时读取Excel,引入了其他程序,可以从Windows任务管理器里观察内存的占用情况
  • 对读取Excel的VI进行动态调用,可以表明附加文件(如本文中的Excel)路径和动态VI路径的获取方式,虽然它们在Windows中的同一个文件夹下,但获取路径的过程有细节上的区别。本文主要为了表明这一点。
  • 读取Excel的VI采用如图1所示的调用Excel属性节点和方法节点的方式,LabVIEW有一套和Excel交互数据的库,是收费的,外企很重视授权问题,我用的LabVIEW是授权的,在没有购买这个库的情况下还是采用比较原始的方式操作Excel。个人学习的话无所谓,NI官方为了推广似乎也不是很重视版权,不过企业使用还是不要带来不必要的麻烦。
    3 D3 I0 A4 n1 x2 E
    7 x) F% h) x, w9 J
1451943-20190110221457175-1686133385.png
图1
: O" |0 K) X1 [$ J' A6 O9 O
进入正题。写好图1的读取Excel的VI后,建立两个项目,两个主VI分别用直接调用和动态调用的方式来调用它,构建一个简单的状态机,再加上一点简单的算法就可以了。待读取的Excel就是A1到J10单元格分别写下1到100. 具体见图2和图3. 图2中获取应用程序的类型是为了区分是以VI运行还是以exe运行。以exe运行时路径会多出一层虚拟文件夹,后面会有更详细的说明

7 }/ |: ~( B$ o; b: \
1451943-20190110221635965-1675040536.png
图2
0 I, [8 p, v5 ]1 x- v* T* {- C3 R4 I
1451943-20190110221731550-235438963.png
8 z2 R" u  S5 ]2 f+ G, }
因为是直接调用,所以当把Direct Call(即主VI)添加到项目中时,被直接调用的子VI自动出现在了“依赖性”目录中,Build完成后,把Excel文件拷到exe相同的目录,如图4

) K( f4 m$ M% s; }) E2 T- R
1451943-20190110221928443-1709286608.png
图4

. _( A% X" Z- @6 Q
生成exe也正常运行,不过可以看到如图5所示,在没有打开Excel文件的情况下,Excel进程正在运行。直到关闭exe应用程序,Excel进程才会自动结束。
而且直接调用时所有子VI也都被加载到内存中,如果是很多子VI组成的大型程序,会占用大量内存。尤其是当VI后期不再被调用时,这些内存也无法释放。
1451943-20190110222036502-879895950.png
图5
2 z* f! ]# }6 i" O, K) c$ k
下面来看动态调用。动态调用只在VI被调用时才加载进内存,调用完成后释放相应内存。
首先编写如图6的子VI,它被主VI直接调用,又作为主调函数动态地调用“Read Excel.vi”
1451943-20190110222154954-2069606621.png
图6

4 ~1 T( ~7 S9 I) s( M
然后主VI调用上面子VI时,需要传递的实参就是“Read Excel.vi”(即需要被动态调用的VI)的路径,以及要读取的Excel文件的路径。
这里VI路径这一项容易出问题,因为VI和Excel文件在同一目录,所以很自然的会写成如图7这样,用同一个根目录组合出两个路径。(只截图初始化部分,其余部分不变)
1451943-20190110222229472-752912640.png
图7
4 T2 f/ m- A( X7 c& T" u5 |4 X+ _2 d
上面的VI运行起来完全可以实现我们需要的效果,如果点击白色运行箭头的过程中一直观察Windows任务管理器,可以看到Excel进程出现了1秒钟左右就又消失了,然后程序的功能也完全没有问题。于是开始生成exe。
创建的过程就没有直接调用那么顺利了,如图8所示,因为“Read Excel.vi”没有被直接调用,所以不会出现在“依赖性”里面,也就没有出现在这个工程里。显然无法继续Build
1451943-20190110222325086-2089717430.png
图8

' W1 P- h; ~' p; M6 `+ D6 ]7 `: ]
这个问题解决起来比较容易,既然“Read Excel.vi”没有自动进入工程,我们就手动把它添加进来,然后Build时放到“总是包含”里面,如图9,就可以生成exe了
1451943-20190110222400183-978115634.png
图9

: b  L3 T- [8 f+ {
Build完运行exe,结果如图10,找不到“Read Excel.vi”。而且通过第三条“动态VI路径”可以看出软件希望找到这个VI的完整路径并不存在,自然是找不到的。读不到Excel,后面的计算等功能自然就不能用了
1451943-20190110222437178-636158575.png
图10
7 L0 [, c5 k% K: N+ b, a, B0 T: S1 M
如果改成图11这种路径设置的方式,即只拆分一次路径再组合成动态VI的路径。exe运行界面第三个路径同样显示了系统寻找动态VI的路径,是在“动态调用.exe”这个虚拟文件夹,Build过程中把动态VI包含在了“总是包含”里,就是为了实现这个。
运行效果如图12,没有错误且可以实现功能
1451943-20190110222513935-1306863299.png
图11
1451943-20190110222543349-575475345.png
图12

  t. Z) D8 Q; r. w. P9 J
总结一下本文要表述的要点
  • 动态VI调用使程序变得更复杂,但是对于比较耗资源且不频繁调用的VI,动态调用对优化内存很有帮助。本程序的读取Excel只在初始化时调用一次,读取到数据后不再被调用,且被调用时占用较多系统资源,是很适合使用动态调用的
  • 附加文件(如本文的Excel文件)的路径需要区分应用程序类型是VI(Deployment System)还是exe(Run Time System)。以exe运行时,因为多了一层虚拟文件夹,因此需要多拆分一次路径
  • 动态VI的路径不用区分应用程序类型,都是拆分一次。对于以VI运行,拆分一次之后就是VI所在的文件夹;对于以exe运行,拆分一次之后是虚拟文件夹,只要Build时把动态VI添加到“总是包含”即可。
    # z) h- U2 y# Q. l$ n. Q% ~$ d( g" Z9 Y
    - Y$ a6 I) J; P. n

" k# J% _& c$ C9 J6 ~
本程序设计一个动态调用读取Excel,就是同时涉及到了上面2,3两条,可以作对比参考。
9 d, J& F. t7 V( |( |6 V5 h6 P
最后提一下,如果程序是图7那种不正确的方式,只是会导致程序在没有动态VI的地方寻找它,我们只要把这个VI复制到程序希望找到它的位置,程序依然可以正常运行,如图13,即使客户机没有安装LabVIEW不能识别VI文件也可以。
1451943-20190110222614281-489166742.png

; h1 X( y: T' |# E5 B
IDAQ-USB-6009数据采集卡

升级   2.51%

发表于 2022-1-20 14:30:58 | 显示全部楼层
在线课堂
2021年新起点 新气象
回复 支持 反对

使用道具 举报

升级   67.85%

发表于 前天 10:59 | 显示全部楼层
厉害厉害,学习了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|小黑屋|无图浏览|手机版|网站地图|虚拟仪器论坛 ( 沪ICP备13044638号-3 )

GMT+8, 2022-5-29 17:23 , Processed in 0.026129 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表