2011年7月15日,第二稿
4.3 程序框图对象的深入探索
我们已经对开发环境所提供的构建图形化程序的一些基本代码有了初步的了解,比如节点中的函数、内置VI和Express VI等等,这些都属于程序框图中的对象。
这些程序框图对象为我们实现图形化程序设计提供了强有力的支持和帮助。特别值得我们注意的是:LabVIEW本身已经完全具备了通用编程语言的基本特性,作为通用编程语言来使用应该说并不存在任何内在的局限性。但是由于它对自控领域待处理任务的高度抽象处理导致它更适合特定领域的应用。
LabVIEW适合特定领域的应用是因为它具备了对待处理任务高度的抽象机制、代码重用机制、以及与硬件无缝连接的特点等等。这些特点使得LabVIEW并不限定它的使用者是否具备专业的程序设计员的资格,所以它更多的使用者是来自科学家和项目工程师。
LabVIEW究竟是如何做到这点:让科学家和项目工程师成为的程序的设计者(非专业的程序设计员)?
这些程序框图对象为我们实现图形化程序设计提供了强有力的支持和帮助。特别值得我们注意的是:LabVIEW本身已经完全具备了通用编程语言的基本特性,作为通用编程语言来使用应该说并不存在任何内在的局限性。但是由于它对自控领域待处理任务的高度抽象处理导致它更适合特定领域的应用。
LabVIEW适合特定领域的应用是因为它具备了对待处理任务高度的抽象机制、代码重用机制、以及与硬件无缝连接的特点等等。这些特点使得LabVIEW并不限定它的使用者是否具备专业的程序设计员的资格,所以它更多的使用者是来自科学家和项目工程师。
LabVIEW究竟是如何做到这点:让科学家和项目工程师成为的程序的设计者(非专业的程序设计员)?
4.3.1 图形化语言的抽象机制
实现计算机程序设计的本质就是对复杂度的管理和控制。复杂度包含了两种含义:计算机底层代码的复杂度和待处理任务的复杂度。事实上,图形化程序语言对这两种复杂度都进行了高度抽象处理。
其实除了机器语言外,任何计算机语言都具备了抽象机制。比如汇编语言就是对实体机器语言的再度抽象处理,但它仍依赖于特定的处理器。而Fortron、BASIC、C等语言是对汇编语言的再度抽象处理,此时已经不在依赖于特定的处理器。可是,这些编程语言所做的抽象处理仅仅体现在对计算机本身的抽象处理。这类似于建立了一种机器语言模型,其实而对待处理任务本身并没有提供本质上的帮助。因为人们在使用这些语言进行程序设计时,必须还要创建待处理任务的模型(建模),并且必须成功建立机器模型和待处理任务的模型的一些必然关联关系。而这种机器模型和待处理任务的模型的关联关系的建立往往需要特殊专业程序员来实现。
面向对象编程似乎是解决、处理复杂问题的最佳方案,可以它依然无法避免需要专业的程序员来进行程序设计。对于大多数工程师和科学家而言,这是一个无法逾越的屏障。
图形化语言通过对计算机底层代码复杂度和待处理任务复杂度的强有力抽象处理(建立在C++的基础上),彻底改变了这一现象。
在图形化语言中,控件(接线端)经过高度抽象处理后,以对象的形式呈现在设计者面前,作为程序框图中的对象,设计者并不需要预先确定它的数据类型或预先设置变量。但是通过控件这个对象我们仍然可以管理和使用控件中的数据,包括它的外观。
这种高度抽象处理的另外结果就是:我们完全不必关心它们的生存周期和如何进行销毁处理等其它语言中所必需的一些处理机制。
控件或节点间的数据传递是依赖于连线来实现的,同时连线也作为考量节点间数据类型是否一致的一种重要手段。
经过抽象处理的函数更加直观易于理解,比如一些运算符和操作符,甚至完全符合我们过去所学习过的一些基本知识。
例4-5 C语言中运算符和操作符与图形化语言运算符和操作符的对比
C语言中的运算符:
+(加);-(减);*(乘);/(除)。
而图形化的表达方式更直观,更符合过去所学到的知识,参见下图。
其实除了机器语言外,任何计算机语言都具备了抽象机制。比如汇编语言就是对实体机器语言的再度抽象处理,但它仍依赖于特定的处理器。而Fortron、BASIC、C等语言是对汇编语言的再度抽象处理,此时已经不在依赖于特定的处理器。可是,这些编程语言所做的抽象处理仅仅体现在对计算机本身的抽象处理。这类似于建立了一种机器语言模型,其实而对待处理任务本身并没有提供本质上的帮助。因为人们在使用这些语言进行程序设计时,必须还要创建待处理任务的模型(建模),并且必须成功建立机器模型和待处理任务的模型的一些必然关联关系。而这种机器模型和待处理任务的模型的关联关系的建立往往需要特殊专业程序员来实现。
面向对象编程似乎是解决、处理复杂问题的最佳方案,可以它依然无法避免需要专业的程序员来进行程序设计。对于大多数工程师和科学家而言,这是一个无法逾越的屏障。
图形化语言通过对计算机底层代码复杂度和待处理任务复杂度的强有力抽象处理(建立在C++的基础上),彻底改变了这一现象。
在图形化语言中,控件(接线端)经过高度抽象处理后,以对象的形式呈现在设计者面前,作为程序框图中的对象,设计者并不需要预先确定它的数据类型或预先设置变量。但是通过控件这个对象我们仍然可以管理和使用控件中的数据,包括它的外观。
这种高度抽象处理的另外结果就是:我们完全不必关心它们的生存周期和如何进行销毁处理等其它语言中所必需的一些处理机制。
控件或节点间的数据传递是依赖于连线来实现的,同时连线也作为考量节点间数据类型是否一致的一种重要手段。
经过抽象处理的函数更加直观易于理解,比如一些运算符和操作符,甚至完全符合我们过去所学习过的一些基本知识。
例4-5 C语言中运算符和操作符与图形化语言运算符和操作符的对比
C语言中的运算符:
+(加);-(减);*(乘);/(除)。
而图形化的表达方式更直观,更符合过去所学到的知识,参见下图。
C语言中的简单操作符:
==(等于);!=(不等于);=>(大于等于);<=(小于等于)
==(等于);!=(不等于);=>(大于等于);<=(小于等于)
这些图形化的表示方法即使是没有学习过C语言的学生,也会看出它们的实际用途。
从另一方面,图形化语言对待处理任务也进行了高度的抽象处理。比如一些需要经常使用的字符串的处理、数组处理、文件I/O等函数;内置VI中也包含了大量的测试分析处理和仿真子程序。而Express VI则更加快了创建和执行特定任务的时间和方法。当然,图形化语言还创建了其它特殊的数据结构或数据类型,比如波形数据结构和变体数据类型等等。
这种对待处理任务也进行了高度抽象处理的做法,大大降低工程师和科学家在程序设计中的难度。
从另一方面,图形化语言对待处理任务也进行了高度的抽象处理。比如一些需要经常使用的字符串的处理、数组处理、文件I/O等函数;内置VI中也包含了大量的测试分析处理和仿真子程序。而Express VI则更加快了创建和执行特定任务的时间和方法。当然,图形化语言还创建了其它特殊的数据结构或数据类型,比如波形数据结构和变体数据类型等等。
这种对待处理任务也进行了高度抽象处理的做法,大大降低工程师和科学家在程序设计中的难度。
例4-6 加深对生成正弦信号中#s的理解
正弦信号生成中的“采样信息”不太好理解,通过这个例子可以很好的展示波形数据中#s的实质意义,参见下图。
正弦信号生成中的“采样信息”不太好理解,通过这个例子可以很好的展示波形数据中#s的实质意义,参见下图。
从这个实例中可以看出,#s就是波形数据中一个周期内所包含的数据点数。通过修改这个参数从上图中可以清楚的看到这种关系。
从这个例子中也可以认识到,正弦波形中的#s是正弦信号的一个周期内所包含的数据(数组),而正弦波形是包含正弦信号数组和时间标识dt(Fs的倒数)的一种数据结构。
从这个例子中也可以认识到,正弦波形中的#s是正弦信号的一个周期内所包含的数据(数组),而正弦波形是包含正弦信号数组和时间标识dt(Fs的倒数)的一种数据结构。
4.3.2 图形化代码的重用机制
图形化的编程语言有没有语法定义或明确的语法说明?
图形化程序设计的基础依赖于函数(函数选板)所提供的基本功能。这些函数作为图形化代码的标准部件提供给设计者使用,而函数的具体功能和使用方法则通过帮助文件加以说明,程序运行又是依据图形化语言的数据流运行机制,所以正如我们所见到过的一样,图形化语言中没有确切的语法定义或明确的语法说明。
图形化语言的实质是采用了一种标准代码(函数)重用的程序设计方式。由于它们是经常使用的图形化代码,所以它的基本功能和使用方法也就渐渐被我们所熟知。函数重用是图形化语言最基本的特点之一。当然,我们已经很习惯这种重用方式,并且已经很不以为然。
图形化程序设计的基础依赖于函数(函数选板)所提供的基本功能。这些函数作为图形化代码的标准部件提供给设计者使用,而函数的具体功能和使用方法则通过帮助文件加以说明,程序运行又是依据图形化语言的数据流运行机制,所以正如我们所见到过的一样,图形化语言中没有确切的语法定义或明确的语法说明。
图形化语言的实质是采用了一种标准代码(函数)重用的程序设计方式。由于它们是经常使用的图形化代码,所以它的基本功能和使用方法也就渐渐被我们所熟知。函数重用是图形化语言最基本的特点之一。当然,我们已经很习惯这种重用方式,并且已经很不以为然。
其实节点中的函数、内置VI都是被用来供使用者重用的图形化程序代码。类似于图形化语言中的标准件,使用这些标准件可以创建自定义的图形化部件、组件和模块化的子VI。这些图形化代码本身简洁、明了、并且功能丰富,使用起来很方便,即脱离了机器底层又可以继续重新封装为新的可重用的子VI。
如果我们的程序中需要某些函数没有提供的特殊功能,那就自己来试试设计实现吧。
在工程应用中,有时候我们需要将弧度值转换为角度值(度),或者将角度值转换为弧度值。函数选板上,我们无法找到满足这种直接转换关系的函数。
那就自己设计一个吧!
例4-6 弧度值与角度值(度)的相互转换
程序代码很简单,转换形式通过枚举控件选择实现。在做弧度-度换算时,Case结构中的乘函数被替换为除函数,参见下图。
如果我们的程序中需要某些函数没有提供的特殊功能,那就自己来试试设计实现吧。
在工程应用中,有时候我们需要将弧度值转换为角度值(度),或者将角度值转换为弧度值。函数选板上,我们无法找到满足这种直接转换关系的函数。
那就自己设计一个吧!
例4-6 弧度值与角度值(度)的相互转换
程序代码很简单,转换形式通过枚举控件选择实现。在做弧度-度换算时,Case结构中的乘函数被替换为除函数,参见下图。
封装(图标、接线端、文档)好就可以在其它程序中使用了。
这种函数(内置VI)的重用机制也带来了一个非常实际问题,就是图形化程序的设计者必须对这些函数(内置VI)有足够的了解,否者就不会设计出合理、简单的图形化程序。
所以学习图形化语言不仅要充分了解这些函数和内置VI的基本功能和使用方法,更主要的是多看、多分析其它设计者的程序代码(例子),只有活学才能够达到活用的目的。
其实许多使用者都有这样的体会:修改例程是最简洁、最快的学习方法,同时出现的问题也会最少。“抄袭”是使用图形化语言最基本的技巧之一。
这种函数(内置VI)的重用机制也带来了一个非常实际问题,就是图形化程序的设计者必须对这些函数(内置VI)有足够的了解,否者就不会设计出合理、简单的图形化程序。
所以学习图形化语言不仅要充分了解这些函数和内置VI的基本功能和使用方法,更主要的是多看、多分析其它设计者的程序代码(例子),只有活学才能够达到活用的目的。
其实许多使用者都有这样的体会:修改例程是最简洁、最快的学习方法,同时出现的问题也会最少。“抄袭”是使用图形化语言最基本的技巧之一。
4.3.3 图形化语言异常和错误处理
似乎只有在理想状态下或者是极简单的程序设计我们的程序代码才不会出现问题。其实正如我们的身体并非永远健康一样,程序代码也会出现这样或那样的不正常现象。尽管程序设计者尽量在避免了一些不正确的操作或运算,但是异常现象总还是会出现的。
这样的情况会得到允许吗?参见下图。
这样的情况会得到允许吗?参见下图。
在纯数学计算中,我们绝不允许上面程序框图中的现象发生,因为那是不合法的数据输入状态。可是数值控件接受和显示Inf(无穷大)和NaN(非法数字)的字符是合法的。所以我们要根据程序中的需要来确定如何处理类似的问题,在程序设计中应该避免相似的异常情况发生。
对于任何计算机编程语言,错误的处理一直都是比较头痛的问题之一,原因就是性能良好的错误处理系统很难设计实现。避免错误出现的最好办法就是建立严格的语法限制和依赖于程序员的自身警觉性。特别是图形化语言本身与硬件间的关联性很大,更难以控制异常错误的发生。另外,图形化语言中并没有严格的语法限制,编译器被看成是甄别错误代码的第一道关卡,初始的错误代码不会逃脱图形化编译器的眼睛,它会帮助我们排查初始错误的存在。不过,并不是所有错误都可以被编译器发现,程序在执行过程依然会出现某些不可预计的问题。所以提供一种嵌入在代码中的异常处理机制是必要的。事实上,图形化语言已经提供了一种异常处理机制,这就是“错误簇”。
“错误簇”可以将错误处理直接内嵌于程序代码中,可以直接在异常发生处抛出错误提示。当错误发生时,错误簇会采用一条与程序代码执行路径截然不同路径来执行。正因为如此,所以它不会干扰正常的程序代码执行。这种异常的抛出方式,使得程序具有较强的自我诊断能力。
图形化语言中的“错误簇”也分为错误输入(无错误)和错误输出两种控件。每个“错误簇”中包含了三种元素,分别是:
状态——布尔量,表示错误状态,T=有错误,F=没有错误
代码——32位长整形数,对应于图形化语言的错误编码
源——字符串,说明错误的原因和现象
错误输入(无错误)和错误输出两种控件参见下图。
对于任何计算机编程语言,错误的处理一直都是比较头痛的问题之一,原因就是性能良好的错误处理系统很难设计实现。避免错误出现的最好办法就是建立严格的语法限制和依赖于程序员的自身警觉性。特别是图形化语言本身与硬件间的关联性很大,更难以控制异常错误的发生。另外,图形化语言中并没有严格的语法限制,编译器被看成是甄别错误代码的第一道关卡,初始的错误代码不会逃脱图形化编译器的眼睛,它会帮助我们排查初始错误的存在。不过,并不是所有错误都可以被编译器发现,程序在执行过程依然会出现某些不可预计的问题。所以提供一种嵌入在代码中的异常处理机制是必要的。事实上,图形化语言已经提供了一种异常处理机制,这就是“错误簇”。
“错误簇”可以将错误处理直接内嵌于程序代码中,可以直接在异常发生处抛出错误提示。当错误发生时,错误簇会采用一条与程序代码执行路径截然不同路径来执行。正因为如此,所以它不会干扰正常的程序代码执行。这种异常的抛出方式,使得程序具有较强的自我诊断能力。
图形化语言中的“错误簇”也分为错误输入(无错误)和错误输出两种控件。每个“错误簇”中包含了三种元素,分别是:
状态——布尔量,表示错误状态,T=有错误,F=没有错误
代码——32位长整形数,对应于图形化语言的错误编码
源——字符串,说明错误的原因和现象
错误输入(无错误)和错误输出两种控件参见下图。
对于用户界面VI,错误簇通常是放置在前面板上的不可视区域。而对于子VI则分别放置到前面板的左下脚和右下脚。在连线板上也设置到左下脚和右下脚的连接端。
在图形化语言中,函数通常不具备错误簇的端口(也有例外)而内置VI通常都具有错误簇的输入和输出端口。除了传递错误外,它还有另一个重要的作用就是贯彻数据流的运行机制。这点我们后面会谈到。
为了即时抛出异常,最常用的模式(模版)就是带错误处理的子VI框架。这个模板能够保证在有错误时可以快速通过本VI,进入下一个节点。没有错误发生时,执行本VI的程序代码。
在图形化语言中,函数通常不具备错误簇的端口(也有例外)而内置VI通常都具有错误簇的输入和输出端口。除了传递错误外,它还有另一个重要的作用就是贯彻数据流的运行机制。这点我们后面会谈到。
为了即时抛出异常,最常用的模式(模版)就是带错误处理的子VI框架。这个模板能够保证在有错误时可以快速通过本VI,进入下一个节点。没有错误发生时,执行本VI的程序代码。
建议在设计子VI时,首选这个设计模式。
图形化语言的错误处理包含两种:一种是警告,另一种是错误发生。当然也可以创建自己的错误代码、信息等。注意:打包时需要将这些文件一起打包。
图形化语言的错误处理包含两种:一种是警告,另一种是错误发生。当然也可以创建自己的错误代码、信息等。注意:打包时需要将这些文件一起打包。
4.3.4 图形化语言与硬件的无缝连接
毋庸置疑,图形化语言与硬件结合并给出相对应的驱动程序是吸引工程师和科学家使用它的最大驱动力(至少我就是如此)。在工程中的应用避免了复杂的硬件设计无疑给我们带来了巨大的方便和好处。甚至可以说相应的拓宽了我们的应用领域。
在接触LabVIEW之前,我所做的设计主要是工频电参数测量仪器。但是无法实现诸如谐波信号发生和谐波信号测量分析等更复杂的内容。
使用LabVIEW之后,我开始介入其它工程应用领域,比如声音、振动的测量和分析;转速的测量、应力的测量、温度的测量、机械视觉等等。因为NI的C系列DAQ模块为我们提供了方方面面的测量功能,我们稍做了解就可以完成以前无法完成的测量任务。这些无疑都是图形化的设计方法为我们所带来的好处。同时,软硬件来自同一个公司会使衔接更方便、更融洽。
诚然,这样的软硬件无缝集成的方式也会给许多初学者和爱好者带来了一些应用上的麻烦。因为目前LabVIEW毕竟不是以软件应用为主体的计算机语言,它与硬件的结合是大多数应用的主体方向。所以学习者本身应该对硬件电路有所了解,甚至对模电、数电、传感器及数字信号处理都要具备相应的基础知识。
相对于工程师和科学家由于软硬件的无缝连接使得他们在工程应用中显得游刃有余,也是获得他们钟爱的原因之一。
在接触LabVIEW之前,我所做的设计主要是工频电参数测量仪器。但是无法实现诸如谐波信号发生和谐波信号测量分析等更复杂的内容。
使用LabVIEW之后,我开始介入其它工程应用领域,比如声音、振动的测量和分析;转速的测量、应力的测量、温度的测量、机械视觉等等。因为NI的C系列DAQ模块为我们提供了方方面面的测量功能,我们稍做了解就可以完成以前无法完成的测量任务。这些无疑都是图形化的设计方法为我们所带来的好处。同时,软硬件来自同一个公司会使衔接更方便、更融洽。
诚然,这样的软硬件无缝集成的方式也会给许多初学者和爱好者带来了一些应用上的麻烦。因为目前LabVIEW毕竟不是以软件应用为主体的计算机语言,它与硬件的结合是大多数应用的主体方向。所以学习者本身应该对硬件电路有所了解,甚至对模电、数电、传感器及数字信号处理都要具备相应的基础知识。
相对于工程师和科学家由于软硬件的无缝连接使得他们在工程应用中显得游刃有余,也是获得他们钟爱的原因之一。











