admin 管理员组

文章数量: 1086019


2024年3月28日发(作者:matlab傅立叶)

LabVIEW设计模式汇总

LabVIEW设计模式汇总

本文归纳了LabVIEW中常用的几种设计模式,介绍了各种设计模式的特点及适用范围,

并提供了每种设计模式对应的典型应用实例。

1 标准状态机

1.1简介

状态机(State Machine)是编程中经典的设计模式之一。状态机对系统所有可能的状态

进行罗列,在每个状态分支中执行该状态的代码,并指明系统要执行的下一个状态。状态机

能清晰和准确地完成与状态密切相关的任务。

1.2结构

图1-1为典型的标准状态机结构。系统包含“Initialize”,“Idle”,“Case1”,“Case2”,

“Stop”五个状态;系统可以在“Initialize”中初始化系统参数,在“Idle”中专门做状态

选择处理,“Case1”和“Case2”为用户自定义的状态分支,“Stop”状态使系统停止运行。

图 1-1 标准状态机结构

1.3要点

(1)状态枚举常量

该枚举常量包含了系统所有可能的状态,每次可以选择一个指定的状态。

(2)带移位寄存器的while循环

状态机通过while循环上的移位寄存器传递下一个要执行的状态,每次循环只能执行一

个条件分支。

(3)条件结构

该条件结构的每个分支对应一个系统的可能的运行状态。

Tips:

可以将枚举常量设计为自定义控件类型。当系统状态需要修改时,只需要修改一次“自定义控件”即

可更新整个程序中所有的枚举常量。

将枚举常量连接到条件结构的选择器接线端后,右击条件结构边框,选择“为每个值添加分支”,可

以轻松地为条件结构实现分支配置。

1.4实例

(1)情景:

使用温度监控系统监测当前温度,当温度超过高温阈值时发出“高温警报”,当温度低

于冷冻阈值时发出“冷冻警报”。

1

LabVIEW设计模式汇总

(2)代码:

详见附件中的“标准状态机”项目文件。

图 1-2 前面板设计

图 1-3 程序框图设计

1.5小结

标准状态的应用非常广泛,它的特点是:

(1)系统的所有状态和转换条件都是可以提前预期设定的,而不是随机产生的;

(2)系统一次只能执行一个状态,不适合做并行任务处理。

如何定义状态是其中最关键的因素。状态机的状态要设计全面,指向明确合理。在着手

编程之前,需要先确定系统的状态转移图,检查是否有状态遗漏,各状态执行代码是否均衡

合理,是否方便以后的需求拓展。

虽然标准状态机具有结构简单,设计方便的优点,但由于它要求系统的状态必须是预知

的,且当前状态只能由上一个状态决定。当系统需要人机交互或者其他复杂操作时,标准状

态机则无能为力,还需要采用其他的设计结构。

1.6参考资料与范例

[1] /content/docs/DOC-14959

[2] /content/docs/DOC-22972

[3] /content/docs/DOC-4594

[4]LabVIEW te Machine Test

2

LabVIEW设计模式汇总

2队列消息处理器

2.1简介

队列消息处理器与标准状态机并没有太大区别,不同点在于队列消息处理器是使用数组

(或队列)来储存状态,而标准状态机使用的是自定义枚举控件传递状态。正因为如此,导

致队列消息处理器有以下优势:

(1)通过数组(或队列)添加状态,可以一次性指定多个即将执行的状态;

(2)状态的数据类型更灵活,可以是数据、布尔、字符串等;

(3)使用队列添加状态时,可以在队列消息处理器循环外部向队列中插入状态,改变状态

的执行顺序。

2.2结构

在LabVIEW中通常使用数组或队列实现队列消息处理器,如图2-1所示。前者使用“创

建数组”和“删除数组元素”函数,后者使用“元素入队列”和“元素出队列”函数。

图 2-1 典型的队列消息处理器

2.3要点

(1)使用数组操作函数的队列消息处理器

“创建数组”函数可以向消息数组中一次添加多个消息,“删除数组元素”函数的“已

删除的部分”接线端与条件结构的选择器接线端相连。

(2)使用队列操作函数的队列消息处理器

“元素入队列”函数可以一次向队列中添加多个消息,如果要新加入的消息立即执行,

请使用“队列最前端插入元素”函数添加该消息,而不是普通的“元素出队列”函数。“元

素出队列”函数读出队列中最前端的消息并同时将其从队列中删除。

2.4实例

(1)情景:

使用温度监控系统监测当前温度,当温度超过高温阈值时发出“高温警报”,当温度低

于低温阈值时发出“冷冻警报”,并同时记录该温度值。

3

LabVIEW设计模式汇总

(2)代码:

详见附件中的“队列消息处理器”项目文件。

图 2-2 前面板设计

图 2-3程序框图设计

2.5小结

队列消息处理器与标准状态机非常相似,队列消息处理器同标准状态机一样,需要注意

分支的合理划分。它的特点是:

(1)传递的消息是动态变化的,可以一次添加多个消息;

(2)消息的数据类型更加灵活,可以是数值、布尔、字符串等;

(3)使用队列传递状态消息时,可以在循环外部向队列中插入消息,方便对队列消息处理

器的控制。

2.6 参考资料和范例

[1] /white-paper/14119/en

[2]/93-222758235745274320108mdashm

[3]LabVIEW ue Message

[4]LabVIEW ued Message

4

LabVIEW设计模式汇总

3事件结构

3.1简介

事件结构是LabVIEW中另一种非常重要的设计结构。在事件结构发明之前,系统需要

不断地“轮询”用户事件是否发生,执行效率非常低。事件结构类似于“中断”功能,只有

当事件发生后,CPU才对其进行处理,事件没发生之前,CPU可以执行其他进程或任务。

事件结构能大大节约系统资源,同时也避免了事件遗漏。

3.2结构

事件结构包含五个基本元素。

(1) 事件选择器——指定本分支所处理的用户事件;

(2) 事件数据节点——用于识别事件发生时LabVIEW返回的数据;

(3) 事件过滤节点——只有在过滤型事件分支中才会显示。过滤事件能在LabVIEW处理事

件之前告知用户该事件已发生,使用户可以自定义处理该事件。

(4) 超时接线端——当在规定时间范围内没有任何指定的事件发生,则进入超时分支;

(5) 动态事件接线端——需要与“注册事件”函数配合使用,可以在程序运行时处理由程序

内部指定希望产生的事件。

图3-1 事件结构

3.3要点

(1)事件结构

用来监测所有的用户交互操作。

(2)while循环

为了多次处理事件,事件结构一般要放在while循环中,且一个程序只需要有一个事件

结构。

Tips:

事件分支中的处理程序越快越好。如果在下一个用户交互事件发生时,上一个事件还没有处理完,则

不能及时响应下一个事件。

通常,LabVIEW只有在用户直接与活动前面板交互时才产生用户界面事件。使用共享变量、全局变量、

局部变量、DataSocket时,LabVIEW不生成事件。但使用值(信号)属性可以产生“值改变”事件。

3.4案例

(1)情景:

使用温度监控系统监测当前温度。当点击“开始采集”按钮时,系统采集一次当前温度

5

LabVIEW设计模式汇总

值;当点击“数据分析”按钮时,系统对最近一次的温度值进行分析,根据温度所处范围发

出高温报警或冷冻报警;当点击“停止”按钮时,系统停止。

(2)代码:

详见附件中的“事件结构”项目文件。

图3-2 前面板设计

图3-3程序框图设计

3.5小结

事件结构是LabVIEW中的经典设计结构,适合用户交互事件较多的应用。但事件结构

需要注意的细节也特别多,处理不好很容易发生锁死或错误。事件结构单独使用时只能执行

一些简单的独立事件,我们往往将它应用在其他设计模式中发挥更大的作用。

3.6参考资料与范例

[1]/reference/zhs-XX/help/371361H-0118/lvconcepts/notify_and_filter_events/

[2]/reference/zhs-XX/help/371361J-0118/lvconcepts/using_events_in_labview/

[3] /reference/zhs-XX/help/371361H-0118/lvhowto/hndlstoploopbool/

[4]/reference/zhs-XX/help/371361H-0118/lvhowto/dynamic_register_event/

[5]LabVIEW 2012examplesgeneraltemplatesTop Level

6

LabVIEW设计模式汇总

4事件状态机

4.1简介

事件状态机是将事件结构与状态机结合的设计模式,常用来处理多个用户界面事件。在

LabVIEW启动界面中通过“创建项目”-“简单状态机”得到的设计模板,即为本节所介绍

的事件状态机。

4.2结构

图4-1为典型的事件状态机结构,包含“Initialize”,“Wait for Event”,“User State 1”,

“User State 2”,“Stop”五个状态;其中,系统初始化后会长时间停留在用于监测用户界

面事件的“Wait for Event”分支。当对应的用户事件产生时,系统转向执行对应的处理分

支,执行完毕后返回“Wait for Event”分支。

图 4-1 事件状态机的基本结构

4.3 要点

(1)事件结构分支

事件结构是事件状态机的核心,完成对所有用户交互事件的实时监测。

(2)其他分支

其他分支的执行速率要尽可能快,否则会影响系统对用户交互事件的响应速率。

4.4实例

(1)情景:

使用温度监控系统监测当前温度。当点击“开始采集”按钮时,系统以10Hz的采样率

连续采集50个温度值;当点击“数据统计”按钮时,系统对最近一次的采集数据进行统计,

计算出最高温度,最低温度和平均温度;当点击“数据存储”按钮时,系统将最近一次的采

集数据进行保存,文件名称为用户点击“数据存储”按钮的时间;当点击“数据回放”时,

系统打开文件对话框,用户选择自己感兴趣的记录文件进行回放;当点击“停止”按钮时,

系统停止。

(2)代码:

详见附件中的“事件状态机”项目文件。

7

LabVIEW设计模式汇总

图 4-2 前面板设计

图 4-3程序框图设计

4.5小结

与标准状态机不同,事件状态机的特点是:

(1)主要用于需要响应多种用户事件的系统;

(2)系统长时间处于一个包含事件结构的状态分支中;

(3)状态机一次只能处理一个分支,不适合做并行的事件处理。

事件状态机适用于简单的事件处理。但事件结构与其他条件分支共享一个循环,当系统

在某个条件分支中执行时间较长时,会导致下一次事件响应延迟。另外,对于一个事件发生,

对应处理该事件的条件分支只能运行一次。如果我们希望用户按下“开始采集”按钮后,程

序连续不断地运行“采集”条件分支,则事件状态机无法满足该需求,我们需要使用其他设

计模式来实现。

4.6参考资料与范例

[1] /content/docs/DOC-11192

[2] /reference/zhs-XX/help/371361H-0118/lvhowto/hndlstoploopbool/

[3] LabVIEW 2012examplesgeneraluievents (Full).llbNew Event

8

LabVIEW设计模式汇总

5主从设计模式

5.1简介

主从设计模式由一个主循环(Master)和一个或多个从循环(Slave)组成。该设计模

式将任务分配到多个循环中并行处理,提高了系统效率,体现了LabVIEW支持多线程的优

点。

利用通知器一对多的信息传递特点,主从设计模式常常用来同步控制几个速率不同的并

行循环任务;利用通知器潜在有损的传输特性,可以用来低速执行数据显示,但不适合于数

据记录。

Tip:通知器类似于通信中的广播方式,一点发出消息,其他所有接收点都可以同时接收到,因此特别

适用于一对多的信息传播。通知器操作函数不缓冲已发送的消息,如果消息被发送后没有任何节点在等待,

则当另一消息被发送后数据将丢失,通知器的执行类似于单元素,有损耗的绑定队列。

5.2结构

图5-1为主从设计模式的基本结构,程序上方的while循环为主循环(Master),下方

的循环为从循环(Slave)。主循环通过通知器操作函数控制从循环运行。

图 5-1 主从设计模式的基本结构

5.3要点

(1)一个主循环,多个从循环

多个从循环同时接收主循环的命令控制,但它们的执行速率可以不同。

(2)通知器

只能在主循环内使用“发送通知”函数,从循环内使用“等待通知”函数。

Tip:注意各通知器(或队列)释放引用的时机。如果从循环中的“等待通知”函数还在执行,而其

他程序部分已经释放了该通知器的引用,则会发生错误。

5.4实例

(1)情景:

系统同时监控环境的温度和湿度。当点击“开始采集”按钮时,系统开始同时采集用户

指定个数的温度值湿度值,“开始按钮”的文字说明变为“正在采集”,当采集结束后恢复为

“开始采集”。当点击“退出”按钮时,系统停止运行。

(2)代码:

9

LabVIEW设计模式汇总

详见附件中的“主从设计模式”项目文件。

图 5-2 前面板设计

图 5-3 程序框图设计

5.5小结

由于通知器的“一对多”特性,主从设计模式经常被用来控制几个不同速率的循环。但

由于通知器使用潜在有损的传输机制,如果主从循环的执行速率不同,常常会发生数据丢失

现象。如果需要高速和大量的数据传递,这种设计模式就不太合适,推荐使用生产者和消费

者模式。

5.6参考资料与范例

[1] /content/docs/DOC-29591

[2] /content/docs/DOC-14758

[3]LabVIEW s Data with

10

LabVIEW设计模式汇总

6生产者/消费者(数据)

6.1简介

在生产者/消费者(数据)结构中,生产者不断“生产”数据,通过队列传递给消费者

进行“消费”。该结构的一个突出特点就是队列充当了生产者和消费者循环之间的“缓存”

作用,生产者循环和消费者循环速率可以不同。当生产过剩,缓存区内的数据会越来越多;

当消费过快,缓存区数据会越来越少,当缓存为空时,消费者变为等待状态,直至缓冲区中

出现可用数据。在生产者/消费者(数据)结构中,最常见的问题就是内存溢出,此时需要

提高消费者循环的执行速率或降低生产者循环的速率。

6.2结构

图6-1为生产者/消费者(数据)的基本结构。程序上方的while循环是生产者循环,生

成所需要的数据。程序下方的while循环是消费者循环,完成数据处理。两者通过队列操作

函数完成数据传递。

图 6-1 生产者/消费者(数据)基本结构

6.3要点:

(1)while循环:并行循环充当“生产者”和“消费者”的角色。

事实上,生产者/消费者(数据)模型中,不拘泥于只使用两个循环,根据实际需要,

可以使用多个“生产者”,也可以使用多个“消费者”。但由于消费者从队列中取出元素后会

将原数据从队列中删除,因此多个消费者共存时,消费者消费的将会是不同的数据。因此,

在多个“生产者”或者“消费者”并存时,它们之间的数据传递也会变得复杂,编程时需要

留意。

(2)队列函数:在并行循环结构之间传递数据。

编程者可以灵活使用各个队列操作函数。例如使用“队列最前端插入元素”可以使消费

者接收到最新的数据。

6.4实例

(1)情景:

11

LabVIEW设计模式汇总

使用温度监控系统监测当前温度,系统采样率为100Hz。当温度超过高温阈值时发出

“高温警报”,当温度低于冷冻阈值时发出“冷冻警报”。

(2)代码:

详见附件中的“生产者/消费者(数据)”项目文件。

图 6-2 前面板设计

图 6-3 程序框图设计

6.5小结

在工业应用中,往往需要同时采集和处理大量数据,因此生产者/消费者(数据)设计

模式的应用非常广泛。它的特点是:

(1)多线程同步执行,程序执行效率高;

(2)适合大量的数据流处理。

生产者/消费者(数据)结构并没有涉及人机交互过程,如果需要进行大量的人机交互,

可以采用生产者/消费者(事件)结构。

6.6 参考资料与范例

[1] /content/docs/DOC-14758

[2] /content/docs/DOC-8962

12

LabVIEW设计模式汇总

7生产者/消费者(事件)

7.1简介

生产者/消费者(事件)设计模式与生产者/消费者(数据)设计模式非常类似,区别是

两者处理的对象不同,前者为数据,后者是事件。

在生产者/消费者(事件)结构的生产者循环中,事件结构保持监测前面板产生的用户

交互事件,并将事件信息送入队列;在消费者循环中,根据队列中的事件信息执行对应的处

理操作。相比事件状态机,生产者/消费者(事件)体现了LabVIEW支持多线程的特点,提

高了系统的执行效率。

7.2结构

图7-1为生产者/消费者(事件)的基本结构,由while循环,事件结构和传递事件信息

的队列组成。

图 7-1 生产者/消费者(事件)基本结构

7.3要点

(1)事件结构

专门用来监测所有的用户交互操作。

(2)

while

循环

遵循程序中最好只有一个事件结构的原则,生产者/消费者(事件)结构一般只使用一

个生产者,但可以有多个消费者(需要用到多个队列)。

Tip:推荐使用的循环同步停止方式

当生产者循环监测到用户按下“Stop”按钮时,将“停止”消息写入队列,消费者循环接收到该消息

后转向“停止”分支,在该分支中,程序将“True”传递给循环条件接线端。

7.4实例

(1)情景:

温度监控系统监测当前温度。当点击“开始采集”按钮时,系统开始连续采集50个温

度值,采样率为10Hz;当点击“数据统计”按钮时,系统对最近一次的采集数据进行统计,

13

LabVIEW设计模式汇总

计算出最高温度,最低温度和平均温度;当点击“数据保存”按钮时,系统将最近一次的采

集数据进行保存;当点击“数据回放”时,系统打开文件对话框,用户选择自己感兴趣的记

录文件进行回放;当点击“停止”按钮时,系统停止。

(2)代码:

详见附件中的“生产者/消费者(事件)”项目文件。

图 7-2 前面板设计

图 7-3 程序框图设计

7.5小结

生产者/消费者循环(事件)结构适合需要处理多个用户事件的系统。但该结构也存在

缺点,例如生产者发出一次指令,消费者循环只能运行一次。但在实际的数据采集应用中,

我们更希望生产者发出“开始”指令后,消费者循环能开始连续采集,而不是只采集一段数

据。因此,单一的生产者/消费者(事件)结构也有一定的局限性。

7.6参考资料与范例

[1] /content/docs/DOC-30005

[2] /content/docs/DOC-2145

[3] /content/docs/DOC-14974

14

LabVIEW设计模式汇总

8 混合设计模式

8.1简介

在实际工程应用中,用户的需求往往是多元化的,既需要数据连续采集和处理,同时还

希望系统能及时响应自己的特殊操作。但标准设计模式能实现的功能往往比较单一,要么只

能处理分立的几个事件,要么只能执行不涉及任何用户交互操作的连续数据任务。可见,在

复杂的系统任务中,单一的设计模式已经不能满足需求,我们往往会用到组合了多个标准设

计模式的混合设计模式。

混合设计模式能结合各个设计模式的优点,满足更多的任务需求。但不可避免地,功能

越强大,系统结构也越复杂。本节给出了一种典型的混合设计模式,实现了温度测量系统的

数据采集、存储和分析功能。在LabVIEW自带的项目范例“连续采集与记录”也是一种典

型的混合设计模式,但程序结构较复杂,供感兴趣的读者参考。

8.2结构

本节介绍的一种混合设计模式如图8-1所示。该结构是由一个生产者/消费者(事件)

与两个消息队列处理器组合而成:

图8.1 一种典型的混合设计模式结构

8.3要点

(1)指令中心

程序上方的两个循环组成系统的指令中心,采用生产者/消费者(事件)模式设计,实

现监测用户事件和分配任务命令的功能。

15

LabVIEW设计模式汇总

(2)功能模块

程序下方的两个循环是系统的功能模块,采用消息队列处理器模式设计,完成系统的两

个独立功能。功能模块可以在自身内部产生消息,也可以接收指令中心的消息。

功能模块的设计结构可以多种多样。如果要连续执行,可以采用队列消息处理器,如果

只需要分步骤执行一次,使用标准状态机就可以。

(3)队列(或通知器)

指令中心和功能模块,以及功能模块之间往往有很多数据交流。队列和通知器是两种主

要的数据传递方式,两者的区别是:队列适合“多对一”的传递方式,通知器适合“一对多”

的传递方式,但通知器属于潜在有损的传输机制,不适合用于高速大量的数据处理过程。

8.4案例

(1)情景:

设计温度监控系统,能同时控制连续的温度采集、存储和报警功能,允许用户自由设置

系统参数和查看历史记录文件。

(2)代码:

详见附件中的“混合设计模式”项目文件。

图8-2 前面板设计

图8-3 程序框图设计

Tips:

16

LabVIEW设计模式汇总

 队列消息处理器中需要注意的问题

(1)指令中心发出的“停止”命令建议使用“队列最前端插入元素”函数,而不是普通的“元素入队

列”函数,以便立即停止功能模块;

(2)在功能模块的“停止”分支中要执行清除消息队列操作,消除队列中残留的消息(“开始”)影响,

否则循环不会停止。

(3)注意释放队列(或通知器)引用的时机。避免释放队列(或通知)引用之后,还有“元素出队列”

和“等待通知”VI在运行。一般将所有释放引用放在程序最末端执行。

 子VI与主VI的数据传递

在子VI的循环内的显示控件不能实时将数据传递到主VI。解决的办法有两种:使用“控件引用”函

数;使用队列。

8.5小结

在实际工程应用中,大多数应用的功能需求都会比较复杂,往往需要结合各种基本设计

模式的特点,通过混合设计模式来实现。

结束语

没有一种万能的设计模式能恰好满足世界上所有的应用需求。因此,编程最重要的不是

编程者的技巧,而是编程者的思路。唯有深入领会各种标准设计模式的设计思想,才能将它

们灵活地运用在各式各样的应用中。

附件:

LabVIEW设计模式汇总-

17


本文标签: 事件 队列 结构 系统 循环