1、Click to edit Master title style,Click to edit Master text styles,Second level,Third level,Fourth level,Fifth level,LabVIEW,高级编程技巧,内容概要,National Instruments,公司简介,LabVIEW,高级编程技巧,用户定义的调试指示器,定时循环,基于事件触发的编程,改善,VI,的性能,调用动态链接库,National Instruments:,虚拟仪器倡导者,建立于,1976,年,超过,1,000,种测试测量产品,在,40,个国家设有直属分支机构,,600
2、家系统联盟商,中国,:,研发,区域咨询,技术支持,市场,NI HQ,NI,客户的分布,超过,25,000,个客户分布在多达,80,个国家,财富,500,强中,95,的制造型企业,1.,调试指示器,灵活的调试工具,可详细显示数据线上通过的数据,指示器的操作可以体现,VI,的灵活性和强大功能,传统的调试指示器存在一些缺点,如只能显示数组中的一个元素,用户定义的调试指示器,能显示各种数据类型,可定制指示器外观,可定制指示器处理功能,设置条件断点,定制你的需求,指示器不仅仅可以显示数据,将数据录入文件,对两个指示器之间的执行进行定时,计算总的调用次数或是每秒的调用次数,内建的定制指示器,在数据连线上
3、点击鼠标右键,菜单显示所有相关的指示器,指示器存放在目录,vi.lib_probesdefault,下,Keep graphics below the text and to the right,客户指示器的结构,包含一个控件,控件的数据类型就是所指示的数据线,包含一个指示器,Boolean,类似条件断点,True=,暂停执行,False=,继续执行,Keep graphics below the text and to the right,2.,定时循环,精确的定时,while,循环,多个时钟频率的定时,反馈,动态定时特性,多达,128,个循环优先级,examplesgeneraltimed
4、loop.llb,定时循环的配置,定时循环,3.,基于事件的编程,管理用户界面,通常采用的方法有中断响应和事件驱动,中断响应采用轮询机制处理,非常占用,CPU,资源,还可能会丢失用户界面的响应,事件驱动无需轮询即可捕捉到相关事件,顺序处理捕捉到的所有事件,不会丢失也不会颠倒顺序,事件举例,事件结构不需要轮询就可以捕捉到自定义菜单上的用户选择,ItemTag,返回菜单条目,MenuRef,返回菜单的,refnum,Virtual,Instrument,事件类型,Application,事件举例,:,退出应用程序,超时,Control,事件举例,:,关闭前面板,VI,上的鼠标移动,事件举例,:,改
5、变控件数值,特定控件上的鼠标移动,通知事件和可滤除事件,通知事件,通知,LabVIEW,发生了一个用户行为,;,只能在,Event Data Node,中使用,可滤除事件,在用户界面处理之前验证或改变事件数据,避免影响,VI;,可在,Event Filter Node,和,Event Data Node,中使用,LabVIEW 7,新事件,更多的用户界面事件,动态注册的事件,用户定义的事件,ActiveX,事件,事件结构的组成部分,Event Selector Label,确定观察的事件,Timeout,等待事件的毫秒数,;,缺省值,1(,无限期,),Defaulted Tunnels,新型,
6、tunnel,允许未连线的事件案例提供缺省值,Dynamic Event Terminals,用于动态事件的注册,事件结构的组成部分,Event Data Node,确定事件发生时,LV,提供的数据,与,Unbundle By Name,函数类似,Event Filter Node,确定,Event Data Node,中可提供的数据子集,可供事件案例修改,事件结构的基本使用,通常在,While,循环中使用,每次循环只处理一次事件,其它时间休眠,在事件结构的左侧边框端口上可获得事件数据,事件结构的配置,通过对话框来配置事件,右击事件结构的边框,选择,“Edit Events Handled b
7、y This Case”,事件注册和面板锁定,包含事件结构的,VI,被预留以后,事件就成为,已注册的,已注册事件发生后,会进入队列等待直到相应的事件结构开始执行,事件不会丢失也不会出现顺序混乱,默认情况下,前面板被锁定直到事件被处理完,可以关闭锁定,但只针对过滤事件,VI,变成空闲后,事件被注销,3.1,动态事件,下列情况时,需要动态注册事件:,事件注册只能发生在应用程序的某些部分,在程序运行过程中需要改变哪些,VIs,或控件可以发生事件,在,subVI,中处理事件,而不是仅在注册事件的,VI,中,动态事件,Register For Events,Event Structure,Unregis
8、ter For Events,Create User Event,Generate User Event,Destroy User Event,编程模型,注册,事件,连接到,事件结构,选择,动态事件,注销,事件,3.2,程序产生的,(,用户,),事件,Register For Events,Event Structure,Unregister For Events,Create User Event,Generate User Event,Destroy User Event,用户事件编程模型,创建并注册,用户事件,产生,用户事件,注销,用户事件,消灭,用户事件,用户事件举例,3.3 Acti
9、veX,事件,Register Event Callback,ActiveX,编程模型,注册,ActiveX,事件,选择事件,创建和编辑,Callback VI,总结:事件处理结构,允许在,subvi,中处理事件代码,提供统一的,简化的事件处理机制,用户界面,接口控制,外部代码,硬件触发,用户定义事件,注册和非注册事件,4.,改善,VI,的性能,改进内存使用,使用高效数组函数,谨慎处理字符串和数组,避免不必要的复杂数据结构,减少,I/O,开销,减少,I/O,调用的次数,减少开启和关闭资源的次数,减少屏幕更新,4.1,改进内存使用,LabVIEW,处理了大部分内存管理的细节,资源分配,复制,释放
10、溢出,减少程序框图的大小,提高可读性和稳定性,内存管理自动进行,你不需要过多的干预,理解,LabVIEW,是何时并如何为你“代劳”内存管理的可以大大提高 对内存使用的效率,VI,在内存中的数据结构,Front Panel,Block Diagram,Code,框图编译成机器码,Data Space,Control/indicator,数值,Block diagram,常量,动态定义的数据,Front,Panel,Block,Diagram,Code,Data,Space,VI,何时加载到内存中,始终载入,data,平台符合时载入,Code (Mac OS,Windows,Sun,Linux)
11、Panel,和,Diagram,在必要时载入,(recompiling),Main VI,SubVI,Always in memory,Resident sometimes,Front,Panel,Block,Diagram,Code,Data,Space,Front,Panel,Block,Diagram,Code,Data,Space,内存使用情况,Tools Advanced Profile VIs,勾选“,Profile Memory Usage”&“Memory Usage”,在执行应用程序之前点击“,Start”,状态只在程序执行完成后更新,程序执行过程中内存使用情况不能被查看,
12、监测内存使用,显示内存分配,File Tools Advanced Show Buffer Allocations,内存优化,LabVIEW,尽量减少内存再分配,需要重新分配内存的函数,Build Array,Concatenate Strings,High Memory Reallocation Low Memory Reallocation,最佳内存使用,尽量使用,subVIs,不要滥用全局和局部变量,只在必要时打开,subVI,前面板,高效地创建和处理数组,不使用大的、复杂的数据类型,coercion dots,构建和处理数组,使用具有,inplaceness,特点的数组函数,Inpla
13、ceness,是指函数,in place,操作数据,而不会另外建立一个数据备份,。,Reuses Buffers,May Allocate New Buffers,Allocates New Buffers,子数组,LabVIEW,尽可能的重用内存缓冲,子数组不存储实际的数据,子数组在必要时会生成真实的数组,由于子数组不要对数据进行拷贝,因此提高了程序的执行速度,子数组,子数组函数返回一个,7499x2,的子数组,这个例子程序需要执行2秒钟,2 GHz Pentium 4,子数组,在函数,Array Subset,之前引线,执行只需5毫秒,子数组到真实数组的生成发生在循环之前,4.2,减少,I
14、/O,开销,I/O VIs,比计算操作多花很多时间,把,I/O,调用降低到最少,每次调用传递尽可能多的数据,使用多点,DAQ VIs,而不是单点,VIs,Slow Method,(many I/O calls),Fast Method,(One I/O call),减少开启和关闭资源,Slow Method,Fast Method,使用底层,VIs,来减少开启和关闭资源的次数,Slow Method,中,文件被打开和关闭,100,次,Fast Method,中,文件只打开和关闭,1,次,保持资源的打开状态,使用底层的文件打开和关闭函数,连接文件读写函数,open,read/write,的引用,
15、提高读速度,操作系统不需检查权限、分配新的文件描述符等,提高写文件的速度,允许操作系统缓冲写操作,标准化,LabVIEW,以“大字端”形式读写数据,X86,机器采用“小字端”形式存储数据,选择不需要转换的数据类型如:,U8,I8,String(data),SGL,DBL,可以编程转换,Flatten to string,Type cast,Manual code,4.3,减少屏幕显示的更新,使用高效的,controls,和,indicators,Graphs,和,charts,在接收新数据的时候会重新画图,从而影响执行速度,设计,subVI,的前面板在执行中保持关闭来减少显示开销,使用多点更新
16、的画图方法,最小化,chart,更新的次数,获得最高的数据显示速率,屏幕显示实例,Slow Method(,每次更新一点,),Fast Method(,每次更新,100,点,),减少循环中不必要的计算,避免将产生相同结果的运算放在循环内,避免在循环中不必要的访问全局变量,减少,SubVI,开销,每个,subVI,都会有一些开销,(,大概几十微秒,);,虽然看起来不大,但如果是在一个循环结构中,就会累加出一个很大结果。,在高速运行的循环结构中,不要显示,subVI,的前面板,如果可能,将循环结构移到,subVI,中完成。,全局和局部变量,每一次变量的读操作都会给数据生成一个新的缓冲区,在使用大数
17、组、字符串或复杂数据结构时会带来很大影响,从内存使用和执行速度来看,使用数据线永远是更有效的方法,属性节点,使用属性节点会引起线程间的交换,从而降低效率,如果只是为了更新控件的值,不要使用属性节点,如果同时改变其它属性,更新数值不会造成更大损失,因为线程交换已经发生了,更新前面板控件,GoodBetterBest,创建高效的平行框图,LabVIEW,周期性地在平行循环间切换,使用,Wait(ms)function,确保不太重要的循环占用较少的处理器时间,5.,共享库函数,What?,Windows,中的,.dll,UNIX/Linux,中的,.so,等等,Why?,降低磁盘空间和内存占用,Ho
18、w?,应用程序只在需要的时候调用库函数,程序开始执行以后,由运行链接编辑器来处理所有调用,动态链接库,(DLL),Microsoft Windows,中的一种软件模块,包含可执行代码和可被,Windows,应用程序或其它,DLL,调用的数据,函数和数据只有在运行状态下,被,Windows,应用程序或其它,DLL,调用时才被加载和链接,一个,DLL,包括,:,一个特殊函数,(DllMain),几个编程者自定义来完成常用任务的函数,DLL,特性,不能单独运行的可执行文件,应用程序要求时,由操作系统加载,应用程序把,DLL,代码作为自己二进制文件的一部分来使用,应用程序不需要知道原始,DLL,是由什
19、么语言编写的,也不需要清楚这些功能是如何实现的。,DLL,就像一个有输出函数的黑盒子,LabVIEW,中调用,Shared Library/DLL,Advanced,Call Library Function Node,右击,Call Library Function Node,,选择,Configure,来调用,DLL,中的特定函数,Call Library Function,的配置,指定需调用的,DLL,函数和函数参数,选择,dll,的调用规则,;,对于,Win32 dll,来说,可以是缺省,(stdcall),或,C.,Call Library Function,和,Win32 DLLs
20、函数参数可以是以下类型:,Void,数字型,有符号,/,无符号,8-bit,16-bit,和,32-bit,整数,4-byte,单精度数,8-byte,双精度数,数组,数组数据指针,数组句柄,字符串,C,Pascal,G(LabVIEW),Adapt to Type,DLL,实例,:MessageBoxA,函数,回传类型,函数名,int MessageBoxA(hWnd,lpText,lpCaption,uType),参数,参数,:,HWNDhWnd 32-bit,无符号整数,.,确定,parent window.,此时为,NULL.,LPCSTRlpText C-style string,
21、LPCSTRlpCaption C-style string,UINTuType unsigned 32-bit integer value.,回传类型,:,int 32-bit signed integer,调试,Call Library Function,如果,VI,不执行或者导致死机,检查下列可能,:,DLL,的路径名是否正确,如果错误信息是,function not found in library,检查函数名的拼写、语法和大小写,传递给,DLL,函数的所有参数都有数据线连接到,Call Library Function,图标的输入端口上,.,检查数据类型和参数顺序,使用了正确的调用规
22、则,:C,或者缺省,(stdcall);The Win32 API,使用 缺省,(stdcall),规则,需要更多帮助,请参阅,Using External Code in LabVIEW,手册,Creating DLLs in LabVIEW,编写和,测试,VI,从,VI,创建,DLL,最终应用,程序中,调用,DLL,LabVIEW,中创建,DLL,要创建其它编程环境中可轻松调用的,DLL,需要注意以下几点,:,调用规则,应用程序的结构,输入,/,输出参数,(,包括可选项,),函数原型声明,参数,数组选项,数字量的数组可以是,:,任意整数类型,单,(4-byte),精度浮点数,双,(8-by
23、te),精度浮点数,创建,DLL,时,可以选择如何从,DLL,中传递数据,通过数值或引用,作为数组数据指针或者数组句柄指针等等,根据,DLL,最终如何使用来选择合适的项目,参数,字符串选项,LabVIEW,字符串句柄,00000004text,string lengthstring data,Pascal,字符串格式,04text,string lengthstring data,C,字符串格式,text00,string dataNULL,Character,LabVIEW,中创建,DLL,打开一个新,VI,选择,ToolsBuild Application or Shared Library,.,在,Build Target field,选择,Shared Library(DLL),指定,DLL,的,name,Destination,和,Support file directories.,