4.3 LabVIEW图形化编程语言的编程范式_第1页
4.3 LabVIEW图形化编程语言的编程范式_第2页
4.3 LabVIEW图形化编程语言的编程范式_第3页
4.3 LabVIEW图形化编程语言的编程范式_第4页
4.3 LabVIEW图形化编程语言的编程范式_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

当前正在审批4.3LabVIEW图形化编程语言的编程范式(LabVIEWgraphicalprogramminglanguage,programmingparadigm)版本7

创建于:2010-12-4下午7:01作者jwdz-最后修改:

2010-12-19上午12:35作者jwdz

上一节中曾简要介绍了编程范式和几种常见的编程范式。在本节中,我们将要进一步说明LabVIEW图形化编程语言的编程范式。

首先,我们要给出上节中所提到问题的最终答案。其实答案很简单:LabVIEW是一种多范式的图形化编程语言,它基本适合我们上面所谈到的几种编程范式。这也是上节中给出这几种编程范式的真实目的。

下面我们就来一一的进行简单分析。

4.3.1LabVIEW图形化语言的过程化(命令式)编程

我们已经知道:过程化编程要求程序员必须要知道程序要完成什么,并且告诉计算机如何来进行所需的计算工作,包括每个细节操作。简言之,就是将计算机看作一个善始善终服从命令的装置。

作为LabVIEW的实践者,此阶段可能已经完成了许多图形化代码的程序设计工作,因为我们认为本书的读者对LabVIEW已经有了充分的了解。但是,面对那些已经完成的程序设计,大家可能根本无法感觉到我们在设计中采用了什么样的编程范式。那么图形化语言如何实现过程化编程的呢?

图形化语言过程化编程的表示方法

回顾第3章的部分内容,我们就不难发现:基于数据流编程思想的LabVIEW图形化编程语言中,最基本、最广泛使用的编程范式应该就是过程化(命令式)编程范式。这点对于学习过和使用过这种编程语言的朋友们来讲,我深信,应该是非常好理解的。

在基于数据流的LabVIEW编程思想中,我们所强调的数据依赖性和充分利用公共线程必将导致其程序结构都是基于过程化的。所以采用过程化编程范式是LabVIEW图形化语言最基本、最显著的特征,是我们必须自觉、不自觉采用的基本编程方式。特别是在仪器控制和数据采集过程中,由于图形化语言的自身的点,这种过程化编程范式显得更自然、更容易理解。

下面我们一起来看几个简单的实例。

例-1无相移滤波器

这个实例来自于LabVIEW2010(Mac版)自带的例程(ZeroPhaseFiltering.vi)。这个例子就是依赖数据关系的过程化编程。

图-1无相移滤波器实例

从工程应用的角度看,通常所设计的滤波器的滤波结果对输入信号都会产生一定的附加相移,有时候这个附加的相移是我们不希望出现的,而本例提供了实现无相移的滤波器。这个应用在工程上是很实用的,通过这个实例可以加深对这个内置vi的理解。

还有没有更好的办法来解决这样的问题?当然有,我认为我所设计的“理想滤波器”(相对于周期信号而言)与它有异曲同工之处。其实,“理想滤波器”的性能应该是更佳,因为它也实现了无相移的基波提取,同时给出基波的实际幅值。当然它还可以改进用来提取谐波分量等等。

感兴趣的读者不妨打开链接看看。

例-2利用公共线程的过程化编程

图-2利用公共线程的过程化编程——34401DMM测量温度(RTD)

在LabVIEW程序中利用公共线程实现过程化编程的实例很多,第3章中所描述的内容都与此相关,这里就不一一列举了。

其实,绝大多数的LabVIEW程序设计都是基于过程化编程实现的。或者说过程化编程是LabVIEW中最主要、最基本的编程范式。

图形化语言过程化编程的基本特点

图形化语言过程化编程基本的特点:

图形化语言最基本的编程范式

毋庸置疑,对于图形化程序设计,只要你贯彻数据流的编程思想一些程序自然都是基于过程化处理的。这样的实例我们见到很多,并且也做过许多这样的程序设计。其实,过程化编程并不局限于上面所介绍的数据依赖性、利用公共线程等等方面。比如:顺序结构、状态机、生产者和消费者循环等所展现的程序代码也都属于过程化编程。

这种过程化程序设计的自然性根本无须特别的强调,依据数据流的编程思想人们便会在程序设计中自觉、不自觉的采用这种程序设计方式(过程式编程)。

简略的回顾一下,LabVIEW从诞生到现在的所有版本,一直都以过程化编程为最基本的编程范式,因为这些已经贯穿在LabVIEW的编程思想中。

在测试、测量任务中,过程化的处理方式也是最基本操作模式之一。

自上而下还是自下而上的编程

通常的程序设计有两种基本路线,自上而下和自下而上。基于文本的过程化编程,更强调“自上而下”的设计方式。图形化的过程化编程即可以采用“自上而下”的设计方法,也可以采用“自下而上”的设计方法,当然还可以同时采用这两种设计方法同时进行设计。这些仅仅取决于问题的表述和你的设计习惯。

在通用应用程序设计时,我们常采用事件驱动VIServer或状态机来控制程序的运行(依据GUI的操作),开始时我们并不需要为每个状态都填写代码,只要状态运行机制正确就可以。确定状态运行正确后,我们开始对不同状态撰写程序代码,并且这些代码可以分配给多人分别撰写。

在测试应用程序设计时,我们通常先设计、实现基本测试、分析功能,当这部分工作正常后在开始设计其它的部分,如报告生成等。

实际上,我们习惯于先对涉及到硬件部分(数据采集、仪器控制等)的程序进行整体设计(包括仿真试验),最后综合设计完成其它的部分。

模块化设计

过程化编程的关键是将待解问题分解为自己可以理解的模块。在LabVIEW中模块是以子vi的形式出现的,每个子vi处理一个或多个任务。而子vi更优异的特性是在于可重用。充分利用子vi的设计,实现程序代码的直观可读性和简洁性。

模块化设计子vi是一个非常好的选择,考虑到vi的可重复使用,采用通用式设计是一个有效的解决方案。比如:我们有许多NI的数据采集硬件产品,实际上在做数据采集时可能会根据测试任务选择不同的硬件。事先,我们可以设计一个标准的vi,实现对不同硬件的通道配置。实现的方法很简单,一个枚举常量、一个Case结构外加不同硬件的配置代码。参见下图。

-1模块化的硬件配置

这是一个有效的模块化设计的解决方案。由于NIDAQ产品配置与总线(PCI、PXI、USB、cDAQ)无关,所以它适用于大多数硬件配置。

它的最大好处是增加新的硬件很方便、很容易,仅仅需要添加一个枚举常数和Case结构中新硬件的配置代码。

当然,尽管这种方式提高了vi的重用性,但是同时也会增加vi所使用的内存空间或磁盘空间,包括也增加了vi导入时所需的执行时间。但这些对现代计算机的性能来讲几乎没有什么负面的影响。

如果你注意到:LabVIEW2010的新特性,对模块化的设计方法使用内存过多的说法就应该不存在任何顾虑。因为LabVIEW2010对编译器进行了优化设计,使得vi经过编译后的执行代码会更简单、更直接。这样讲,似乎很难理解,我们针对-1做简单的说明。

在-1中,我们针对不同的硬件设计了不同的配置代码,目的是用模块化的设计方法提高vi的可重用性。实际上,在程序运行中我们仅仅用到了一种硬件的配置代码,也就是由枚举常数所定义的那个Case结构中的硬件,其它Case结构中的硬件配置代码根本没有使用到。LabVIEW2010编译器对此做了处理,在生成的可执行代码中去掉了其它Case结构中根本没有用到的硬件配置代码,近而提高了程序的执行效率。并且,编译本身并不会破坏vi的源代码。

请注意,LabVIEW2010的这个新特性是利用增加编译的时间来换得程序执行时间的降低,从而提高了编译后程序执行代码的执行速度。

(未完待续)

4.3.2LabVIEW图形化语言的事件驱动编程

需要提醒大家的是:本节所要讨论的是图形化语言事件驱动的编程范式。但我们不得不先介绍一些有关事件编程的其它知识。

我们知道:LabVIEW6.1推出了基于事件驱动的编程方法。但是,在LabVIEW较早期的版本中,如LabVIEW6,就已经包含有基于事件通知的编程方法(应该说是一种基于软件的同步机制)。为了更好的说明事件驱动的编程机制,这里先简单介绍一下这部分相关内容。

事件通知是一种同步机制,它允许LabVIEW程序中并行处理部件之间在事件发生时进行相互通知。由于它采用的是利用软件触发的方式发出事件通知,这样就避免了使用轮询技术所导致的系统开销过大的问题。

在程序设计中,可以利用一个事件源(GenerateOccurrence)来通知多个等待事件的用户(WaitonOccurrence),从而起到同步触发的作用。

在函数选板上可以看到这些基于事件通知的内置函数。参见下图。

图4.3.2-1基于事件通知的内置函数

Occurrence一词的意思是发生(事件),它与event是同义词。

在许多教科书中我们可以看到Occurrence函数的一些介绍。但是,在实际的程序范例中,我们真的很少看到使用Occurrence函数的程序(至少我的感觉是这样)。可是在OpenG的vi包中,我们确看到了它的实际应用。这就是它的:OpenG_Wait(ms).vi。

图4.3.2-2OpenGWait(ms).vi

它是用LabVIEW_Wait(ms)函数创建的vi,但比LabVIEW_Wait(ms)函数功能更强大。下面就是它的程序框图。

图4.3.2-3OpenG_Wait(ms).vi程序框图——Case=True

图4.3.2-4OpenG_Wait(ms).vi程序框图——Case=False

它不仅有错误簇输入、输出;还可以设定出现错误时是否停止定时;同时还有一个事件通知的信号输入端。前面几个特点我们这里不谈了(在《LabVIEW——北方客栈》的“videsign”和“OpenG”专栏中已经评述过),这里仅谈谈事件通知这个特点。

众所周知,如果在一个While循环中放置一个长时间的定时器,比如60s,当用户试图使用条件终端停止这个While时,有可能需要等待很长时间(最长120s,为什么?)。参见下面的程序框图。

图4.3.2-5LabVIEW_Wait(ms)函数

这绝对是一件非常令人非常沮丧的事情。因为我们在停止定时后,真的不希望存在过长的等待时间。

现在来回答为什么可能要等待上120s的时间。

因为While循环首先要执行60s的定时循环(初始条件端为“F”),即便是我们在定时开始后马上按下了停止按键,定时循环也要执行完这个定时。在完成这个定时后,条件端检测到停止按键按下后(条件端为“T”),还要在进行一个循环才能结束。所以,最坏的情况下有可能需要等待120s时间。

现在,使用OpenG_Wait(ms).vi就可以解决这个问题,它利用了Occurrence事件通知来消除过长的等待时间。具体的程序框图请参见下图。

图4.3.2-6利用Occurrence事件通知来立即停止定时循环(Case结构假为空)

图4.3.2-6最外面的循环是60s的定时循环,内部是采用Occurrence事件来停止定时的循环。这样我们就可以在任何时候都可以立即停止主定时循环。

其实仅仅使用Occurrence事件通知机制同样可以实现同样的定时功能(不使用Wait(ms)函数或vi),并且也可以立即停止定时循环。在《LabVIEW图形编程》一书中就给出了这样的实例,我们可以一起来看看它的程序框图。

图4.3.2-7利用Occurrence事件通知来消除过长的等待时间(Case结构假为空)

它是利用超时值来做为定时值进行定时处理,并利用Occurrence事件通知来消除过长的等待时间。

这里请注意:基于事件通知的图形化程序代码的运行机制还是基于数据流的运行机制。其图形化代码清晰、直观、易理解。

清楚了事件通知的运行机制,现在我们该回到本节的正题,LabVIEW事件驱动编程。

图形化语言事件驱动编程的由来

我们前面曾经谈到过,计算机可视化操作系统(Mac、Windows、Linux)的陆续出现为LabVIEW提供了广阔的生存空间和持续发展的基本环境。

在可视化操作系统中,人机对话基本上都是通过鼠标、键盘的事件响应来实现的。人们通过鼠标的拖拽、点击实现对计算机最基本的操作,计算机则通过用户事件处理机制来响应和处理来自用户的要求。对于这些事件通常被称为:GUI事件。

尽管在LabVIEW赖以生存的基本环境中,可视化操作系统都是采用用户事件处理机制来响应和处理用户的要求。但是不知道什么原因,在LabVIEW6.1出现之前的早期版本中,人机对话并没有相应的GUI事件处理机制。那时,对用户的操作响应采用的是轮询的方式来检测用户的操作,处理则采用队列的方式来处理用户需求。

轮询的方法有两个缺点:一是,占用CPU的资源;二是,可能遗漏用户的操作请求。

自从LabVIEW6.1推出了事件驱动处理机制后,就完全去掉了轮询的这两个缺点。使得GUI事件驱动占据了用户界面事件响应处理的主导地位。这些事件包括鼠标事件、键盘事件、窗体事件、对象事件等等。

事件驱动机制的建立,使得LabVIEW在处理复杂事情方面能力大大的增强,可以更方便的实现用户的多种需求(不仅仅是GUI事件,还可以处理用户自定义的事件)。这样LabVIEW也就具备了通用编程语言最基本的特性。

图形化语言事件驱动编程的表示方法

图形化的事件驱动代码参见下图。

图-1事件结构的图形化代码

对于事件结构的基本知识介绍,这里将不做更多的讲解。比较具体的讲解和应用我们将会在下一章:《LabVIEW图形化语言的设计模式》中给出。

下面通过一个演示程序来进一步理解事件驱动编程。

例-1事件驱动的演示程序

图-2给出了演示程序的前面版。

图-2事件驱动演示程序的前面版

在前面版中,我们放置了三个控件。Door控件表示一个门(鼠标点击相当于敲门);Numeric控件用来纪录事件的次数(敲门的次数);Event控件用来停止演示程序的运行。下面我们在来看看它的程序框图。

图-3事件驱动演示程序的程序框图

这里我们创建了两个事件源,一个是:“DoorMouseDown”,用来响应和处理用户的敲门事件;另一个是:“EventMouseDown”,用来停止这个演示程序。

“DoorMouseDown”事件处包含3个Case结构。

首次敲门,弹出对话框:“Hello!”;

第2次敲门弹出对话框:“Pleasedonotknockit!”;

之后再敲门将弹出对话框:“Iwillcall"110"”。

感兴趣的可下载看看!

思考题:

在图-3中的Case结构中,“Case2”被设定为“Default”,这是为什么?运行程序试试看,选择Case0或Case1为默认Case结构会出现什么现象?

图形化语言事件驱动编程的特点

下面总结出事件驱动编程的一些基本特点

事件结构框架需与While循环配合使用

如图-1所示,如果仅用单独事件框架,那么无论有多少个事件源、产生多少个事件,该事件结构也仅能响应最先发生的那个事件。也就是说:此时,只有一个事件会得到响应和处理。

为了能够顺利地响应多个事件发生,我们需在事件结构外面加入一个While循环。有了这个While循环,我们就可以响应和处理多次发生的事件,正如我们演示程序所示的那样。

事件结构的停止也应采用事件处理方式

事件结构中While循环的停止,也应采用事件处理的方式完成。如演示程序中的“EventMouseDown”事件的处理方式。也就是说,在程序执行时用布尔常数来控制While循环的条件端来停止事件结构。

图-4停止事件也采用事件处理机制

事件结构不宜处理耗时过长的程序代码

现在我们修改上面的例子,将事件处理中的对话框去掉,换成5s中的定时。参见下图。

图-5为每个事件处理加5s钟定时

在例-5事件驱动的演示程序中,我们为每个事件处理程序(每个Case结构)都加入了5s中的定时。也就是说,事件处理是需要一定的时间。如果事件连续发生会出现什么样的情况呢?我们一同来看看。

运行该程序后,我们马上连续点击3次Door,然后再点击“Evert”。这时我们会发现,程序运行了大约15s后停止下来。

这说明,程序能够响应所有的事件,并陆续执行完所有的事件处理。事件处理时间取决于各个事件处理时间之和。所以我们建议在事件驱动机制中,事件结构中不宜处理耗时过长的程序代码。因为,我们通常希望看到快速响应事件及快速的事件处理。

事件结构中事件处理不宜包含对话框

在图-3事件驱动中,我们使用了对话框来处理事件的响应。实际上,在事件驱动处理程序中这种方式是不可取的、应该尽可能不用的。原因就是:对话框操作可能导致其它事件暂时无法响应。因为,如果对话框没有被及时处理,程序会一直停止在那里等待对话框处理结果。

实际运行该程序我们会发现,在对话框弹

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论