




已阅读5页,还剩12页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
LabVIEW实践之路第二章 强筋健骨:由程序流程的控制展开按照通常的教程,现在一般要介绍各种数据类型,例如数字、字符串、数组与簇等等。不过从程序结构入手,在掌握流程控制VI的同时认识各数据类型应该更有效,毕竟如果老是把目光集中在树木上,那很容易忘了郁郁葱葱的森林。本章仍然通过实例来学习,依次完成For循环、While循环、条件结构、顺序结构、事件结构、公式节点等LabVIEW实例。2.1 循环结构循环结构是任何程序设计语言都必不可少的,尤其是For循环、While循环等。以下将通过实例学习LabVIEW的循环结构以及移位寄存器的用法。2.1.1 For循环看一下右图,For循环的尊容很容易记。左上角N是循环体内程序执行的循环次数,内部的i是当前循环次数(第一次从0开始计数)。LabVIEW的For循环执行过程中是无法中断跳出的,这一点必须明白。另外,虽然左上角的N用来连接总的循环次数值,但许多情况下For循环可以应用“自索引”方法,不用连接N,让循环自动进行,这种方法在数组等类型执行For循环时非常普遍。(其实说白了也很简单,诸如新的JAVA版本也支持数组等类型的迭代而不用先求出数组的length,别急,一会儿给几个例子对比一下) 好的,我们先来最简单的,同时产生1024点的随机数(01之间)和一个周期的正弦波,如图2.1所示。 图2.1 For循环仿真波形上面的例子中For循环次数为1024次,循环体内上部为随机数产生器,下部是正弦函数值。每次循环各产生一个随机数和的正弦值。注意:当循环完成退出时,循环体右侧,边框上连接内外数据的小方框就起到了自动索引的作用:将你各次循环的结果按顺序排列成数组进行输出。当然,有时候我们不需要自索引输出,那可以在索引方框上点右键取消的,不过想一想,取消自索引后输出应该是什么?我问的问题太没有难度了,呵呵。当然,自索引在输入端也是可以使用的,而且会带来意想不到的方便,尤其是同移位寄存器结合使用。闲话少说,下面我们就实现一个求一维DBL数组最大值和最小值的程序。哦,为了养成良好习惯,我们画一下算法的流程简图吧(对了,下面的流程简图说明一下问题帮助编程,相信你能做得更好)。如图2.2所示,为了便于说明问题,我们假定数组非空。我们直接给出了实现的程序,注意,图2.3和图2.4的两个框图程序都能够得到图2.5所示的正确结果,可能其中几个vi、循环两侧的移位寄存器以及2.3中的条件结构有些陌生。除了这些,两个程序有什么不一样吗?图2.3 求数组最大最小值框图程序1图2.4 求数组最大最小值框图程序2图 2.2 算法流程图先说一下有些陌生的东西。图2.3中在循环里应用了条件结构,条件框可对真和假两种情况作出不同的处理,不过不要急,下一小节再讲它。那么数组在开始循环之前使用获得了数组长度,并赋给For循环的循环次数N,这时候在循环内部i就会从0循环递增到N-1,于是我们使用索引数组函数依次获得第i个数组元素。每次获得当前元素后,都同最大值max、最小值min进行比较,以获得整个数组的最大最小值。当然,我们用-初始化max和用+初始化min都是为了从第一个数组元素开始就能够正确的完成最大值、最小值的查找。这儿有一个关键的实现-移位寄存器,也就是循环框上的。你可以在循环框上点右键,选择“添加移位寄存器”便会发现在循环框架的左右出现了一对。没错,移位寄存器是成对出现,它的工作原理是:第i次循环的输出(右侧)即是第i+1次循环的输入(左侧)。具体到图2.3所示的程序,进入循环体时max移位寄存器初始化为-,而min初始化为+。第一次循环时数组元素3读入,分别与max、min的值比较,结果是max、min被置为3;第二次循环时max、min的值都已经变成了3,这一次循环读入2,比较后min的结果置为了2。以此类推,直至循环结束。图2.4功能与图2.3完全一样,注意,为什么For图2.5 程序前面板循环左上角的循环次数N并没有赋值?因为数组进入循环体是使用了自索引(如果你连接数组和For循环体,默认就是自索引),For循环回自动从头到尾依次获取每一个元素的值,对我们编程节省不少力气。另外程序用选择函数代替条件结构,这个函数能够用于大多数双值选择的情况,但必须是相同类型(如从两个整型、两个字符串中根据真假选择),上方输入提供逻辑真时的输出,下方输入则提供逻辑假时的输出,中间则是判别逻辑(真或假)。肯定有学过LabVIEW的小盆友会说,数组最大值、最小值有专门的VI可以调用,不用这么麻烦。没错,数组函数里数组最大值与最小值函数能够直接完成此功能,并且给出最大值、最小值出现的位置。我们举例是为了学习,并且你也可以继续完善我们的例子实现更多的功能。如果我们在程序运行前无法知道循环次数怎么办?或者需要中途可以中断跳出的循环时?当然是While循环了。2.1.2 While循环While循环特征也很明显,除了内部的当前循环次数i同For循环相同外,由于通常用于无法预知循环次数的循环,所以内部的是用来连接跳出循环的条件:输入为真时结束循环。如果你在上点右键,可以选择输入为真时继续循环(即输入为假时结束循环),图标变为。好的,我们先来实现一个简单的While循环:求0+1+2+n的值,置于n是多少,我们就让它随机吧,直到我们点击退出按钮时再停止。最终需要显示n的值和求和的值。程序框图和前面板如图2.6所示。 图2.6 While循环实例使用While循环有几个问题需要注意:1、 计数i从0开始,While循环至少会运行一次。而For循环如果循环次数N设为0(或空数组自索引),则一次也不会循环。2、 合理循环终止方式。如果是通过内部条件触发(如循环3000次后自动停止等),则要注意算法不要有问题;如果是通过点击按钮退出,那要注意按钮的机械动作(后面会讲)和循环条件类型。3、 While循环里面尽量不要出现While循环的嵌套。While循环里面还有While循环很容易导致死循环,而且几乎所有的问题都有不适用嵌套的解决方法。4、 While循环内要根据情况设置延时。许多While循环是需要一直运行来进行事件处理,如果不加延时会全速循环,耗费大量系统资源。而许多情况下,几十甚至几百个毫秒的延时不会对程序的功能和人机交互带来任何问题。许多东西需要在实践中总结和改进,并且经验也不是适用于一切场合的。那么我们再来实现一个While循环的例子:使用While循环绘制图表,我们用到While循环、随机数发生函数、波形图表(chart)、延时函数,如图2.7。图2.7 While循环波形仿真通过调整延时的毫秒倍数,你能很轻松的控制循环的速度。但注意的是,这种定时方式不是一种精确的方法,不能用于非常精密的需求中。还有一点必须强调一下,While循环(包括For循环等)中如果存在并行执行的框图程序,那么只有等到所有程序都执行完一次循环后,才能进入下一次循环的执行。如果出现有快有慢的程序段,那对不起了,等着吧,这里的规矩就是不抛弃不放弃!图2.8很好的说明了问题。 图2.8 循环内程序并行执行在2.8的While循环中,两个红框是并行的程序,其中一个用来处理各种计算等任务,另一个用来检测按钮状态决定是否退出。由于检测状态非常简单,所以瞬时便执行完,而计算任务则需要耗费一秒多时间,所以如果在这期间按钮状态变为了真,对不起,当时是不能退出程序的,等到这一次循环的计算任务也完成了,程序进入下一次循环时才能退出。同样,三个紫色框内是低一层的并行任务,由于其中的For循环最耗费时间,从前面板执行结果可以看出,当最下面的显示“While循环i值”执行完显示到3时,For循环还在努力中,显示为2。所以并行是好东西,但要用好。我曾看到过有人编写的采集程序大致每秒钟循环50次;但由于把一些网络查询反馈等比较耗时的操作放到了采集循环中,就导致了采集程序一直等着其执行完成后才能继续下一次循环,经常会缓冲溢出报错和丢失数据。(那怎么办?后面会说的,别急)2.2 顺序结构顾名思义,顺序结构就是强制程序运行时的前后顺序。有时候我们想将几个程序段按顺序执行,而程序本身并没有连线能够保证这种顺序(还记得前面说的吗?LabVIEW的数据流向是顺着连线从左往右的),那么你可以使用顺序结构。当然,如果连线能保证的,就不要像图2.9的采集程序一样画蛇添足了,因为不使用顺序结构的结果是一模一样的,如图2.10所示。图2.9 带有顺序结构的采集程序图2.10 不含顺序结构的采集程序从上面的图中我们认识了顺序结构的样子之一,顺序结构还有层叠式的,主要是避免前后多个顺序段串起来太长,显示不方便。图2.11所示为顺序结构的两种形式。图2.11 平铺式和层叠式顺序结构顺序结构初始只有一个框,想要添加很简单,直接在框上点右键添加就可以了。下面我们来完成一个顺序结构的程序:获得一段程序运行耗费的时间。这儿将用到获取当前时间的函数-获取日期/时间(秒),在框图的“定时”选板里。程序前面板和框图如图2.12所示。 图2.12 获取程序运行时间上面的框图很简单,就是在程序运行前获取一下当前时间,在程序结束后再获取当前时间,两者之差就是程序运行时间。顺序结构在这儿起了重要的作用。当然,运行一下程序你会发现每次得出的结果有点不同,想一想为什么?如果不加顺序结构上面程序会得到什么结果呢?这个问题我问得太简单了 图 2.13 删除顺序结构后的结果2.3 事件结构事件结构的学习是挺激动人心的。不是说别的东东不重要,而是因为事件结构是实现众多UI事件响应或其他内部事件响应的结构类型。也许你学过VC的事件机制,确实很好很强大,但学习者不能太傻太天真,VC的事件机制学习曲线有点陡(嘿嘿,不如说MFC太陡,陡陡陡)。不过LabVIEW中的事件机制没那么难办,尤其是UI事件。闲话少说,先瞻仰事件结构的尊荣,如图2.14所示。事件结构也是由边框围成的封闭结构,结构内部就是响应特定事件所要执行的程序,结构上方是所要响应事件的名称,即事件分支(图2.14显示的是响应“超时”事件)。注意,以下几句话比较重要,我们一句句解释一下: 图2.14 事件结构1、 一个事件结构可以有多个事件分支,即可以层叠多个框(可以右键添加删除)。不好意思,这一句是废话2、 同一个事件结构里,不能出现两个事件分支都对同一个事件进行响应(注意,是“同一个事件结构里”,不同事件结构就没人管了)。简单说,在一个单位只能“一个萝卜一个坑”,但不限制你去别的单位兼职。3、 同一个事件分支可以同时对多个事件进行响应,也就是说可以“殊途同归”。还有还有,不过先不往下列了,实践之路就得先实践。我们来完成第一个事件结构的例子,是UI事件:判断鼠标是否在前面板内部,先上代码如图2.15。 图2.15 事件结构判别鼠标是是否进入前面板好的,我们来解释一下。程序中的事件结构共有3个事件分支:超时、鼠标进入窗格和鼠标离开窗格。超时是应用程序事件,另外两个则是窗格事件。超时事件左上角连着时间(50毫秒),也就是说当50ms时间没有发生本事件结构中其他任何事件分支时,程序将进入下一个循环,那么很容易想到,如果我们不给超时事件赋值(或赋值为-1),那么程序会一直等待有事件分支发生。以下通过添加“鼠标进入窗格”事件说明事件结构的编辑方法。右键点击事件结构上方的分支列表,选择“添加事件分支”后就进入了“编辑事件”对话框,如图2.16所示。下方“事件源”中选择你的事件的来源,是来自应用程序(如超时事件)、窗格(如本例中的鼠标进入)以及某控件(如按钮、文本框、列表框等等等等)。下方右侧可以选择特定的事件。那么上部的“事件说明符”列表有什么用吗?看到和没有?你可以在当前处理分支里面通过添加多个事件!当然也可以想删谁就删谁别急,下一个例子就会让大家体验一下。在添加了“窗格”的“鼠标进入”事件后,点击确认完成本次添加,这时框图程序的事件结构中就多了该事件分支。为了响应鼠标进入窗格的事件,我们在前面板放置一个字符串显示控件图2.16 编辑事件对话框并赋值为“鼠标进入”,那么就能保证当鼠标进入前面板窗格时就会显示“鼠标进入”字符。按照同样的方法添加“窗格”的“鼠标离开”事件。这时问题来了,我们还想用刚才创建的前面板字符串显示控件来提示“鼠标离开”,怎么办?没法把线连过去啊?那么我们就来使用一种不采用连线的数据流动或共享方法,在这儿可以用局部变量或属性节点(这种方法之后会详细说)等。我们看一下如图2.17如何创建控件的局部变量,很简单,右键!创建完成后,根据需要设置其是读取或写入,我们的例子当然是写入,完成状态字符串的更新。以上的例子很简单,事件结构的每一个事件分支均响应一个事件,并且这些事件都是预定义的系统或UI事件。是不是觉得不够过瘾?毕竟有些事件,特别是非UI事件,是必须由用户自己定义的,这种情况怎么办呢?很简单,看图2.17中的事例-当仿真数据大于0.97时显示该数值并点亮红灯半秒钟(当然,该例中实际上我们可以不用事件结构就能实现该功能,但许多情况下事件结构是不错的选择)。 图2.17 注册用户事件首先告诉大家,注册用户事件的子VI在函数选板对话框与用户界面事件选板下,如右图所示。对于用户自己定义的事件,可以用这些VI来实现,其流程是这样的:首先需要“创建用户事件”,这时需要连接你在事件中所要传输数据的类型给此VI,并且要给其一个唯一的标签,就像图2.17中的;然后注册该事件,因为注册事件后才有了事件句柄(嘿嘿,从VC里面借用该词,不一定准确)可以给处理程序使用;接下来在事件发生的框图内使用“创建用户事件”并将值付给该VI;最后需要在事件结构中处理该事件,创建分支的步骤同前一个例子一样,不过注意的是,事件结构默认样式下边框上没有连接动态事件接线端的位置,那怎么办?答对了!点击右键选中就可以了。各位小朋友一定注意到了,上面例子用到了不少局部变量,对于结束程序的布尔按钮用到了两个,而对于报警灯也用到了两个,这是不需要连线的共享方法(不过我更喜欢用属性节点,嘿嘿,后面会有例子)。我们拿停止按钮来解释一下这种用法。注意,本例中有两个while循环,我们准备用一个按钮来停止。前面已经知道了,由于LabVIEW连线的数据流本质,导致了没有退出循环前,数据流连线无法直接送出去,因此就用按钮的局部变量来实现。这儿必须注意按钮等布尔控件对点击事件的响应方式有多种(右键能查看、修改),后面我们会细说。要保证点击按钮后,两个循环都能退出,我们必须做到按钮为“真”的状态保持到两个循环都退出以后,当然推出以后按钮要置回“假”。上例中是我比较喜欢使用的方法,实质上也是利用了数据流连线连到外面的顺序框上保证了两个循环都能退出。好了,这个例子不多说了,努努力,你肯定能够实现。如果一步步将所有的流程都列出来,那就不是学习,而是纯粹的模仿和重复,加油吧!事件部分再给一个例子吧,就是通过一个事件分支判断到底是鼠标那个键被按下或释放,程序如图2.18所示。 图2.19 一个事件分支响应多个事件上例用一个事件分支响应了两个事件:鼠标按下和鼠标释放,事件添加方式前面说过了,不会忘了?这个例子比较简单,因为两个事件(鼠标按下、鼠标释放)是同一类型的,所以处理起来很简单。好的,我们对于事件结构的学习暂时到这儿,其实在这一部分还看到了多循环并行的使用以及局部变量的妙用。后面还有机会使用事件结构完成非常实用的程序,主要是响应各种按钮事件、菜单事件以及各种自定义事件。当然,饭要一口口的吃,诸如21天精通某编程语言的圣经属于大仙们的读物,作为人类我们可以省省啦。2.4 条件结构条件结构,同样是一个经常会用到的类型,只要有其他编程语言的使用经历,那绝对是小菜一碟。当然,即使没有用过别的编程语言,照样是一碟小菜。条件结构的尊荣在2.1.1中见到过了,默认如右图所示,不再罗嗦。但等等,为什么说“默认”如右图呢?呵呵,这个问题提得好,这个问题提得妙,这个问题呱呱叫!从函数面板里选择条件结构放置到框图程序后,条件结构的左输入端的选择条件是布尔型,即如果输入为“真”,进入一个分支进行处理;而如果输入为假,则进入另一个分支进行处理。那么很简单,我们有时候会使用其他类型的输入作为条件项,如判断计算结果,如果为0,1,2分别进行处理(这是数值型);如判断某字符串是CHN、JPN、USA、WC分别进行处理(这是字符串型);当然还可以是LabVIEW独有的“错误型”,如右图所示。条件结构的用法类于其它编程中的Case结构,我们只要记住以下几点就会基本的用法了(但要用好,还得加加油):1) 一组条件结构的输入条件类型必须是相同的。很容易理解,你如果输入时布尔(真、假),那就不能出现其他的,如果是数字也都得是数字(而且是整形哦),字符串就得都是字符串。2) 各输入必须能够覆盖所有可能的选项。这句话其实也容易理解,布尔量只有真、假两种情况,没有第三种。如果是数字或字符串怎么办?那也得覆盖所有的可能。想一想,怎样能够快速达到这条件?嗯,和其他编程语言一样,设置一个默认选项!除了你明确规定的输入外,其他都默认了不久全覆盖了?比如输入类型为整型,我们分别单独处理输入为0和1的两种情形,然后再添加一个默认选项,当输入条件不是0/1时都归它了。添加的方式很简单-右键!3) 条件结构向外的输出必须各分支均提供才行。嗯,这句话不是太准确,换句话说,要想以数据流连线的方式输出,那每一个条件结构分支均要连到该输出接点,否则程序时不可执行的。还是晕?看右图,条件结构为“真”时右侧有一个浮点数值的输出,但如果你在其它的条件分支中不理会这个输出,那就像图中所示,条件结构框上的输出显示为空心的,整个程序也是不可执行的-直到所有分支都给它连上线,即使是默认值也行。接下来开始实践,实践之路呀,先来一个简单的“根据数值给出字符串提示”的例子吧,如图2.20所示。图2.20根据数值给出字符串提示上面的例子过于简单了,简直没有什么可讲的,那直接进入下一个例子,如图2.21,稍微难一点点:求平方根值。对了,在这儿我们就不考虑虚数了,所以如果输入值是个负数,那就得提示错误,不能求其平方根(顺便说一句,这个例子是LabVIEW帮助里的,嘿嘿)图2.21求平方根值嗯,好吧,我承认选择结构很简单,不过他的作用确实无可替代。另外,选择结构嵌套、选择结构直接处理错误类型等都是非常实用的编程方法。2.5 常用其他结构类型除了上面介绍的几种常用结构类型外,还有禁用结构、公式节点、MathScript节点、反馈节点及定时结构等提供给我们完成各种复杂的程序,下面分别做简单的介绍。2.5.1 禁用结构禁用结构在LabVIEW中是个新鲜的东东,包括程序框图禁用结构和条件禁用结构两种。为了能更好的理解,我们可以这样来理解:程序框图禁用结构主要用于调试方便,而条件禁用结构则有点类似于C语言中的#ifdef宏定义,并能用于解决程序的跨平台等问题。注意哦,两者都不能像条件结构那样在程序运行过程中动态选择分支,所以你在结构框左端找不到条件分支选择器。哦,还是抽象?那就实践一下。我们来假设一个场景:在进行信号处理提取特征量时,最初不知道使用均值还是有效值更好,于是我们想在调试时测试一下,确定下来后把另一种方法的框图“注释掉”。如图2.22为该程序框图禁用结构实例。 图2.22 程序框图禁用结构程序框图禁用结构可以有一个启用项和多个禁用项,即当前只有一个你选定的选项被编译执行。如上图,我们使用了两个分支:均值Mean计算和有效值RMS计算,哪一个好用就设成启用即可。等等,那这和条件结构有什么区别吗?我们也可以用个条件结构,想用哪一个就给一个值选中该条件就行。区别还是有的:条件结构中运行哪一个分支是在程序运行过程中才决定的,即使你给的其他选项永远也不会运行,那程序运行时照样会将所有的分支装入内存;而禁用结构就很简单了,就像被注释掉一样,编译后没有各禁用选项的事了。一句话:运行效率有区别,尤其是复杂选择分支情况下。还有一种禁用结构叫条件禁用结构,它与上面的程序框图禁用结构的区别在于,条件禁用结构根据我们设定的符号的值来判断决定执行哪个分支的程序。注意,这种判断不是像条件结构一样通过分支选择器来获得的,而是系统自动获得的。看一下2.23简单的例子:根据操作系统的不同执行特定代码。通过设置TARGET_TYPE为Windows(也可为Mac/Unix/PocketPC等等),你可以让自己的程序具有跨平台执行能力,呵呵。当然,使用条件禁用结构还有别的好处,不过最好是在工程里面使用,这样会有更多选项,并且可以在工程中配置自己所需要的符号,可以多试试图2.23 条件禁用结构2.5.2 公式节点该节点的使用是把双刃剑:你可以在公式节点内部放入复杂的计算过程代码(与C语言及其相似),然后调用执行,完成运算但打住:如果你能够通过C把代码编出来,还要学习LabVIEW干吗?仅仅想做个界面吗?不管怎么说,这东西在一些场合下还是很有用的。直接上例子2.24所示,公式节点框左端可以根据需要添加并命名输入(里面代码使用),根据需求连上对应格式的输入值,右端就是输出了,框图内部则是你写的代码。看一下,好像和C语言没什么区别?如果想弄清楚公式节点的编程规范,简单,在公式节点的帮助里面就有。任何一款好的软件,其帮助系统应该都是优秀的教程,LabVIEW也不例外。图2.24 公式节点2.5.3 MathScript节点这是同MATLAB交互的工具,用法呢其实和公式节点差不多,节点内部是MATLAB的代码。MATLAB里有众多好东东哦,比如神经元网络工具箱、数字图像处理工具箱、小波包工具箱等等。不过有几点要强调一下:肯定要有这两个工具才能运行;注意LabVIEW和MATLAB版本的兼容
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年甘肃省省直机关公开遴选公务员笔试题及答案解析(A类)
- 2025年电焊工试题及答案中级
- 知识付费培训合同课件
- 知识产权维权培训小结课件
- 钳工基础知识培训方案课件
- 钱江潮观潮安全知识培训课件
- 知识产权培训申请课件
- 知识产权培训基地申报课件
- 2025年安全生产管理综合测试题及答案解析
- 钢筋质检员基础知识培训课件
- 故宫博物馆院课件
- 2025年8月16日贵州省黔东南州事业单位遴选笔试真题及答案解析(专业水平测试)
- 豌豆栽培种植技术
- 2025-2026秋季学年第一学期学生国旗下演讲稿(20周):第一周 新程启航礼润心田-开学典礼
- 2025年教师招聘小学语文真题及答案
- 2025年突发疾病应急演练方案(脚本)
- 幼儿园保安人员培训记录
- 2025年运城社区专职工作人员招聘真题
- 设备晨会管理办法
- 钢材供货方案及保证措施范本
- 云南省委党校行政学院考试真题(附答案)
评论
0/150
提交评论