2011年2月9日,第一稿
2011年7月29日,第二稿
2011年7月29日,第二稿
5.5 控制程序流程——循环结构
毫无疑问,循环结构是编程语言中必不可少的运行结构之一,图形化语言也不利外。图形化语言提供了两种循环结构,一种是For循环(重复做同一个操作N次),另一种是While循环(重复做同一个操作不定的次数)。
此外,循环中还可以加入移位寄存器或反馈节点。
此外,循环中还可以加入移位寄存器或反馈节点。
5.5.1 For循环及它的图形化表示法
For循环可以控制某段程序在循环体内重复执行的次数。
For循环应该是最古老的图形化代码之一,应该包括在LabVIEW 1.0中。至少我们在LabVIEW 1.2(1989年)中就已经看到它了。并且多年来外形基本上没有发生什么改变,参见下图。
For循环应该是最古老的图形化代码之一,应该包括在LabVIEW 1.0中。至少我们在LabVIEW 1.2(1989年)中就已经看到它了。并且多年来外形基本上没有发生什么改变,参见下图。
在函数选板》结构》可以找到For循环结构。将其拖拽到程序框图中,并适当调节它的大小就完成了一个For循环的创建。参见下图。
For循环的主体结构为一个可伸缩的方形架构框(放置需要循环的程序代码)。方框内部包含两个可见的元素,一个是总数(N)接线端;另一个是计数(i)接线端。在LabVIEW 8.5之前,For循环没有条件停止功能。现在已经增添了这个功能。
N——总数接线端
在标准状态下:N的数值决定For循环执行的循环次数。
i——计数接线端
显示For循环已经循环过的次数。
N——总数接线端
在标准状态下:N的数值决定For循环执行的循环次数。
i——计数接线端
显示For循环已经循环过的次数。
5.5.2 For循环的数据流运行机制
当程序执行到For循环时,For循环总是首先读取总数接线端N的数值,然后依据这个数值决定循环体内代码的循环次数。
具体如果:
N=0,For循环不执行循环;i=不确定
N=1,For循环执行一次循环后停止;i=0
N=n,For循环执行n次循环后停止;i=n-1
对于For循环也可以有条件的中止循环,这需要为For循环配置条件端。具体操作是:鼠标右键单击For循环的边框,在弹出的快捷菜单中选择:条件接线端。参见下图的示例。
具体如果:
N=0,For循环不执行循环;i=不确定
N=1,For循环执行一次循环后停止;i=0
N=n,For循环执行n次循环后停止;i=n-1
对于For循环也可以有条件的中止循环,这需要为For循环配置条件端。具体操作是:鼠标右键单击For循环的边框,在弹出的快捷菜单中选择:条件接线端。参见下图的示例。
当我们确定使用条件接线端后,总数计数端就会出现一个小红点,表示此循环带有条件控制端。尽管上图中N=10,在条件端的控制下For循环仅执行了5次就停下来。
For循环的特殊之处
我们来看数组处理这样一个例子,这个例子说明For循环只会按元素个数最少的情况进行处理。
For循环的特殊之处
我们来看数组处理这样一个例子,这个例子说明For循环只会按元素个数最少的情况进行处理。
尽管总数计数端设定为100,一个数组为5元素,另一个数组为9元素,For循环的实际运行次数仅为5次,说明For循环只处理最少的数组元素。
For循环的并行
For循环的并行性能可以加快循环的处理速度:在LabVIEW8.6之前For循环没有并行特性,如果要想实现快速循环必须采用人为并行处理。从LabVIEW2009后为For循环设计了并行处理机制。参见下图给出的示意。
For循环的并行
For循环的并行性能可以加快循环的处理速度:在LabVIEW8.6之前For循环没有并行特性,如果要想实现快速循环必须采用人为并行处理。从LabVIEW2009后为For循环设计了并行处理机制。参见下图给出的示意。
实现For循环并行特性的具体操作是:鼠标右键For循环边框,在弹出的快捷菜单中选择:配置循环并行;系统会弹出一个对话框来配置并行For循环。参见下图。
点击确定后,我们就会在For循环的框架中看到一个[P]端,参见图5-46。
实际上,LabVIEW2010的优化改进比LabVIEW2009并行For循环的处理速度又提高了两倍以上。
实际上,LabVIEW2010的优化改进比LabVIEW2009并行For循环的处理速度又提高了两倍以上。
5.5.3 While循环及它的图形化表示方法
While循环也是一种循环结构,与For循环不同的是:它重复执行循环体内的程序代码直到满足某种条件为止。
在函数选板》结构》可以找到While循环结构。将其拖拽到程序框图中,并适当调节它的大小,并配置相应的条件端就完成了一个While循环的创建。参见下图。
While循环的主体结构为一个可伸缩的方形架构框(放置需要循环的程序代码)。方框内部包含两个可见的元素,一个是计数(i)接线端,另一个是循环条件控制端。
i——计数接线端
显示While循环已经循环过的次数。
循环条件——根据循环条件端的设置(真或假),确定循环停止的逻辑关系。
相对于For循环而言,While循环的使用率更高。可以说,几乎在绝大部分程序中都可以发现它的存在。如:事件结构、状态机、连续数据采集等等。
i——计数接线端
显示While循环已经循环过的次数。
循环条件——根据循环条件端的设置(真或假),确定循环停止的逻辑关系。
相对于For循环而言,While循环的使用率更高。可以说,几乎在绝大部分程序中都可以发现它的存在。如:事件结构、状态机、连续数据采集等等。
5.5.4 While循环的数据流运行机制
While循环的数据流运行机制是这样的:当程序执行到While循环时,首先检查While边框上的所有数值作为初始值(如果存在的话),然后执行循环体内的程序代码,此时如果循环外的数据发生变化,将不会影响到循环的内部。执行完毕后查看条件端子的布尔值(设定为真时停止),如果该数值为T则退出循环;如果该值为F则继续进行循环,然后再次查看条件端,直到该值为T时才停止循环。
依据While循环的数据流运行机制,我们可以看出:对于While循环而言,它至少会执行一次。下面看示例。
依据While循环的数据流运行机制,我们可以看出:对于While循环而言,它至少会执行一次。下面看示例。
图 5-49 While循环运行一次的示例
Paragraph. 单击此处进行编辑.
上面的示例给出While仅运行一次的程序框图。条件端与不同布尔常数配置就可以实现While循环运行一次。
其实,这两个图中有没有While循环都一样,程序的运行和结果都是一致的。有时候我们利用这个特点来规范图形化代码的分布,避免代码的随意放置(乱丢乱放)。
如果我们将停止控制开关放在While循环的外部会发生什么现象呢?我们来看下面这个例子。
合理的控制While循环运行
其实,这两个图中有没有While循环都一样,程序的运行和结果都是一致的。有时候我们利用这个特点来规范图形化代码的分布,避免代码的随意放置(乱丢乱放)。
如果我们将停止控制开关放在While循环的外部会发生什么现象呢?我们来看下面这个例子。
合理的控制While循环运行
通过实际运行,我们会看到While循环要么执行一次(开关=T),要么就无限期执行下去(开关=F)。
这里再次展现了数据流的基本概念,因为依据数据流的工作原理,所有输入到While循环的数据必须在执行循环前传输,而循环的输出数据只有循环结束后才能够输出。
所以当开关为T时,While循环只执行一次,当开关为F时,While将会无限期的运行下去。这时的循环实质是死循环,设计中一定要避免这样的情况发生。这里也间接的告诉我们这样一个事实,While循环的控制量应该在循环内产生。下图合理的使用While循环的方法。
这里再次展现了数据流的基本概念,因为依据数据流的工作原理,所有输入到While循环的数据必须在执行循环前传输,而循环的输出数据只有循环结束后才能够输出。
所以当开关为T时,While循环只执行一次,当开关为F时,While将会无限期的运行下去。这时的循环实质是死循环,设计中一定要避免这样的情况发生。这里也间接的告诉我们这样一个事实,While循环的控制量应该在循环内产生。下图合理的使用While循环的方法。
实际上,上图解决了While循环合理运行时的逻辑关系。这并不能保证While循环真正的合理运行。因为在上图中,While循环将以最高的循环速度进行,这将会占用了大量的CPU资源,甚至会使得其它程序运行受阻。解决这个问题的简单办法就是在While循环中插入延时节点。参见下图。
当然,如果While循环中的程序代码执行时间足够长的话(相当一定的延迟时间),也可以不插入定时节点。还有一个解决方法是使用定时While循环。
5.5.5 循环中添加移位寄存器
移位寄存器的概念来自于数字电路,图形化语言的For循环和While循环中也引入了这个概念。For循环和While循环中的移位寄存器可以纪录保存以前循环的迭代数据,有些类似于数据存储单元。这样我们就可以利用移位寄存器进行一些简单的数据处理,比如计算平均值等等。移位寄存器不仅仅可以做数学运算处理,由于它的多态性它还可以接受不同类型的数据。比如状态机中也大量的使用了非数字类型移位寄存器。
移位寄存器的创建很简单,鼠标右键单击For循环或While循环的边框,在弹出的快捷菜单中选择:添加移位寄存器。此时会在For循环和While循环的左右边框上自动添加一个寄存器对,参见下图。
移位寄存器的创建很简单,鼠标右键单击For循环或While循环的边框,在弹出的快捷菜单中选择:添加移位寄存器。此时会在For循环和While循环的左右边框上自动添加一个寄存器对,参见下图。
右边的寄存器端子(向上的箭头)在完成每次循环后用来保存数据,移位寄存器在下一次循环开始之前将该数据传递到左边的寄存器端子(向下的箭头)。假如我们用一帧一帧来表示移位寄存器的循环状况,可参考下图的示意。
上图中我们借用帧的表现手法,演示了移位寄存器(数据)与循环间的关系。需要注意的是这里为移位寄存器进行了初始化。移位寄存器时多态的,可以接受数值、字符串、数组等数据类型,大多数移位寄存器应用时都必须进行初始化。假如我们将上图中的初始化值0去掉,就会发现,每重复运行一次,它的输出值都会得到加3的结果。这表明移位寄存器具有纪录保存数据的能力,前提是它必须驻留在内存中。
利用这种关系我们可以进行数据保存和简单的计算。下面就看个例子:
例 5-12 计算平均值(移动平均)
利用While循环和移位寄存器实现移动平均计算。
利用这种关系我们可以进行数据保存和简单的计算。下面就看个例子:
例 5-12 计算平均值(移动平均)
利用While循环和移位寄存器实现移动平均计算。
上图中随机数发生器作为数据源,它的数据分布如图中的白色线段所示。现在我们通过移位寄存器对随机数进行移动平均处理(取8个数据平均),减少随机数的分布误差(趋向于0.5),移动平均的结果如上图中红色线段所示,由图可见平均效果很好。
实际上,移动平均往往被用来对测量值的分布进行平均,以期测量结果能够逼近测量的平均值。
使用移动平均需要注意几个问题:
所谓移动平均是指:所有数据移动的参加平均处理,比如第0-7个数据为一组,1-8,2-9.....。利用移位寄存器恰好实现了这种迭代。
移动平均结果中的前8个数据是无效数据,因为它们的初始值都是0,只有从第九个平均数据之后的平均结果方有效。
这里还有一个工程上实际应用中会遇到的问题,有网友曾问到使用平均是否可以提高测量结果的准确度。
其实,这是两个根本不同的概念,不能混为一谈。平均是一种纯数学的处理方法,平均的结果可以降低数据本身的波动性,逼近所有数据点的平均值。可是测量获得数据不同,它是通过传感器、数据采集部件获得的测量数据,如果这些部件本身就存在着误差,此后任何平均处理也不会减少这部分误差的影响,只会逼近这个误差。换句话说,如果传感器、数据采集部件都是理想的(不存在误差)此时再采用平均处理可以改善测量结果的准确度(实质是减少了波动量,逼近了准确度)。
实际上,移动平均往往被用来对测量值的分布进行平均,以期测量结果能够逼近测量的平均值。
使用移动平均需要注意几个问题:
所谓移动平均是指:所有数据移动的参加平均处理,比如第0-7个数据为一组,1-8,2-9.....。利用移位寄存器恰好实现了这种迭代。
移动平均结果中的前8个数据是无效数据,因为它们的初始值都是0,只有从第九个平均数据之后的平均结果方有效。
这里还有一个工程上实际应用中会遇到的问题,有网友曾问到使用平均是否可以提高测量结果的准确度。
其实,这是两个根本不同的概念,不能混为一谈。平均是一种纯数学的处理方法,平均的结果可以降低数据本身的波动性,逼近所有数据点的平均值。可是测量获得数据不同,它是通过传感器、数据采集部件获得的测量数据,如果这些部件本身就存在着误差,此后任何平均处理也不会减少这部分误差的影响,只会逼近这个误差。换句话说,如果传感器、数据采集部件都是理想的(不存在误差)此时再采用平均处理可以改善测量结果的准确度(实质是减少了波动量,逼近了准确度)。
5.5.6 反馈节点
实际上,反馈节点与移位寄存器的作用相同,所不同的是使用反馈节点可以减少连线的长度。所以二者是可以相互进行转换的。下面看一个例子:
例 5-13 创建数组
使用反馈节点来创建一个数组,参见下图。
例 5-13 创建数组
使用反馈节点来创建一个数组,参见下图。
当然使用移位寄存器也是可以的,参见下图。
从数据流的观点看,反馈节点的引入似乎破坏了数据流的关系。因为我们一般确定数据是从数据源传递到数据终端的,可是反馈节点破坏了这一基本原则。它允许数据逆向流动,即从数据的终端反馈到数据输入端(反馈节点上的箭头指出了数据的流动方向)。
其实,这里千万不能与模拟电子电路中运算放大器反馈的概念混为一谈。在模电中,反馈的概念是实时进行的,而反馈节点中反馈的概念是异步进行的(迭代是关键)。实质上,反馈节点就是移位寄存器的简化版本。所以对反馈节点的要求同样适应于移位寄存器。
其实,这里千万不能与模拟电子电路中运算放大器反馈的概念混为一谈。在模电中,反馈的概念是实时进行的,而反馈节点中反馈的概念是异步进行的(迭代是关键)。实质上,反馈节点就是移位寄存器的简化版本。所以对反馈节点的要求同样适应于移位寄存器。




















