LabVIEW 入门阶段系统化培训教程(精校版全本)

LabVIEW 入门阶段系统化培训教程(精校版全本)

💡 核心摘要
  1. 本文为 培训专用版本手册,已优化 PDF 导出分页规则(采用 HTML 分页符控制)。
  2. 引入了教材大纲设计:规范了“第 X 章”命名,补全了各章的“章前导读”以及“知识自检清单”。
  3. 为所有大章下的子标题添加了 1.11.22.1 等规范序列号,并通过 CSS 移除了嵌入文件的原生重复标题与书签冲突。

LabVIEW 入门阶段的内容主要为路线图的第一部分,会进行系统的培训,相关资料的分享,以及自己一些常用工具,最后有一份练习题送上。

LabVIEW 学习路线图 中有完整的学习路线图,可以进行阅读。

LabVIEW 学习路线图全景导图LabVIEW 学习路线图全景导图

第一章 数据流与 LabVIEW 核心机制

💡 本章导读

本章主要介绍图形化编程语言(G 语言)的核心灵魂——数据流(Dataflow)机制。与传统的文本语言按代码行顺序执行不同,LabVIEW 节点的执行仅由数据是否到达端子决定。本章将帮助你建立直观的图形化编程思维,并理解数据在虚拟仪器(VI)中的流动轨迹。

1.1 什么是 LabVIEW?

💡 核心摘要
  1. 主要内容:美国国家仪器有限公司(NI)成立于 1976 年。公司创立之后,一直致力于将传统的测试测量仪器与个人电脑相连接。当时,传统仪器上最主流的 I/O 接口是 GPIB (General Purpose Interface Bus) 接口。而 NI 公司早年最成功的产品正是个人电脑上的 GPIB 接口卡,…

  美国国家仪器有限公司(NI)成立于 1976 年。公司创立之后,一直致力于将传统的测试测量仪器与个人电脑相连接。当时,传统仪器上最主流的 I/O 接口是 GPIB (General Purpose Interface Bus) 接口。而 NI 公司早年最成功的产品正是个人电脑上的 GPIB 接口卡,通过这块插卡,传统的测试测量仪器与个人电脑实现了数据通信,在个人电脑上即可以读取仪器测量到的数据,也可以发送命令控制仪器的操作。因此,NI 的工程师们很自然的就开始考虑如何开发一款软件,更方便灵活的操控硬件,同时也就有更强大的数据分析展示能力。

  在公司成立的第十个年头,也就是 1986 年,NI 发布了一款名为 Laboratory Virtual Instrument Engineering Workbench(实验室虚拟仪器工作台)的软件,它的缩写名就是 LabVIEW。

(从左到右):Jack MacCrisken,Jeff Kodosky 和 Jim Truchard,LabVIEW 发明人。(从左到右):Jack MacCrisken,Jeff Kodosky 和 Jim Truchard,LabVIEW 发明人。

  (从左到右):Jack MacCrisken,Jeff Kodosky 和 Jim Truchard,LabVIEW 发明人。

  G 语言是图形化编程语言(Graphical Programming Language)的缩写。LabVIEW 不是唯一的图形化编程语言,但它是当今最完善、功能最强大的一种图形化编程语言。 因此,LabVIEW 几乎成为了图形化编程语言的代名词 —— LabVIEW 有时也被称为 G 语言。我们可以这样理解,LabVIEW 是一种开发环境(类似的,Visual Studio 也是一种开发环境),在这个环境下编写的代码就是 G 语言代码(类似于在 Visual Studio 下写出的 C 代码)。

  LabVIEW 常常被误认为是一种仅应用于工业测控领域的应用软件,而不算作是一种编程语言。误解的原因有两个:首先是因为它和其它常见的编程语言完全不同。初次见到 LabVIEW,人们很容易联想到电路板布线、工业总线配置等应用软件;其次,LabVIEW 主要被使用在测控领域,很多用户对它还缺乏了解。

  既然是一门编程语言,在使用 LabVIEW 的时候,就应该按照程序设计的思维来考虑。使用 LabVIEW 开发软件与使用其它语言的开发过程是相同的。一般来说,都需要经历以下五个步骤:收集需求、设计、编码、测试、发布及维护。如果有其它计算机语言的使用经验,是会对学习 LabVIEW 语言有一定帮助的。但是,在学习 LabVIEW 的时候,需要格外注意图形化编程语言与文本编程语言的差异之处,有些文本语言的使用经验不能直接套用在 LabVIEW 上。本书在介绍 LabVIEW 时,会提及 LabVIEW 区别于其它文本编程语言的独特之处,并将它与其它文本编程语言进行对比,以帮助文本编程语言的程序员注意到这些区别。

1.2 LabVIEW 学了有什么用?

💡 核心摘要
  1. 主要内容:LabVIEW 编程语言有很多优点,是测试测控行业最牛的编程语言。因此,当需要在这些领域开发计算机软件时,可以优先考虑 LabVIEW。

LabVIEW 编程语言有很多优点,是测试测控行业最牛的编程语言。因此,当需要在这些领域开发计算机软件时,可以优先考虑 LabVIEW。

测试测量:LabVIEW 最初就是为进行测试测量而设计的,因而测试测量也就成为了当前 LabVIEW 被应用得最为广泛的领域。经过多年的经营,LabVIEW 在测试测量领域获得了广泛的支持。至今,大多数主流的测试仪器、数据采集设备都拥有专门的 LabVIEW 驱动程序,使用 LabVIEW 可以非常便捷地控制这些硬件设备。同时,用户也可以十分方便地找到各种适用于测试测量领域的 LabVIEW 工具包,这些工具包几乎覆盖了用户所需的所有功能。用户在这些工具包的基础上再开发程序就容易多了。有时甚至于只需简单地调用几个工具包中的函数,就可以组成一个完整的测试测量应用程序。

控制:控制与测试是两个相关度非常高的领域,从测试领域起家的 LabVIEW 自然而然地首先拓展至控制领域。LabVIEW 拥有专门用于控制领域的模块:LabVIEW DSC。除此之外,工业控制领域常用的设备,数据线等通常也都带有相应的 LabVIEW 驱动程序。使用 LabVIEW 可以非常方便地编调各种控制程序。

仿真:LabVIEW 包含了多种多样的数学运算函数,特别适合进行模拟、仿真、原型设计等工作。在设计机电设备之前,可以先在计算机上用 LabVIEW 搭建仿真原型,验证设计的合理性,找到潜在的问题。在高校教育领域,有时受条件限制,无法完成课程中提及的与某些硬件相关的实验。这时如果使用 LabVIEW 进行软件模拟,几乎可以达到同样的效果,使学生不致失去实践的机会。

儿童教育:由于图形外观漂亮且容易吸引儿童的注意力,同时图形比文本更易于被儿童接受和理解,所以 LabVIEW 非常受少年儿童的欢迎。对于没有任何计算机知识的儿童而言,可以把 LabVIEW 理解成是一种特殊的 “积木”:把不同的原件搭在一起,就可以实现自己所需的功能。著名的可编程玩具 "乐高积木",使用的就是 LabVIEW 编程语言。儿童经过短暂的指导就可以利用乐高提供的积木搭建成各种车辆模型、机器人等,再使用 LabVIEW 编写控制其运动和行为的程序。除了应用于玩具,LabVIEW 还有专门用于中小学生教学使用的版本。

快速开发:根据我对自己所参与的一些项目的统计,完成一个功能类似的大型应用软件,熟练的 LabVIEW 程序员所需的开发时间,大概只是熟练的 C 程序员所需时间的五分之一左右。 所以,如果项目开发时间紧张,应该优先考虑使用 LabVIEW,以缩短开发时间。

跨平台:如果同一个程序需要运行于多个硬件设备之上,也可以优先考虑使用 LabVIEW。LabVIEW 具有良好的平台一致性。LabVIEW 的代码不需任何修改就可以运行在常见的三大台式机操作系统上:Windows、macOS、Linux。 除此之外,LabVIEW 还支持各种实时操作系统和嵌入式设备,比如常见的 PDA、FPGA,以及运行 VxWorks 和 PharLap 系统的 RT 设备。

1.3 LabVIEW 该怎么学?

💡 核心摘要
  1. 主要内容:版本推荐:

版本推荐:

LabVIEW 2018 带来了一个新的 Python 子面板。您可以从 LabVIEW 代码调用 Python 代码,在这个 AI 的时代,Python 带来的便利如果被运用起来,Python 的数据处理与分析,加上 LabVIEW 的数据流呈现一定会事半功倍。

任何人学习 LabVIEW,直接推荐 NI 官网能下载到的最新的社区版 LabVIEW。2020 版本解决了类接口的问题;2022 Q3 版本开始支持 Conda 虚拟环境;2023 Q3 版本开始程序界面可以随意缩小放大。从 LabVIEW 2018 版本开始,已经是一个非常完整的版本了。

数据流:

多次提到数据流,那么什么是数据流。 常规文本编程语言(以及大多数计算机)基于一个称为控制流的概念,该概念旨在通过显式排序使事情一步一步地发生。LabVIEW 语言被正式称为数据流语言。 它所关心的是每个节点(一个接受输入并将其处理为输出的对象)在执行之前都有其所有输入可用,简单的比喻就是要用线把功能串起来,相当于运行路径。 这是一种新的编程方式,在宣布自己是合格的 LabVIEW 程序员之前,您必须习惯这种方式。 虽然使用数据流编程很容易,但它可能会受到限制,因为您必须在数据流模型的范围内操作。 这个约束也迫使你编写运行良好的程序。 一个写得很好的 LabVIEW 程序以从左到右和从上到下的顺序流动,但执行顺序始终由数据流控制。我们在编程的时候,一定要遵循这样的原则,否则会出现奇怪的问题,比如数据滞后,数据紊乱。反过来说,如果遵循这些限制,那么将会帮助你感受到可视化数据帧级别的魅力,这是其他编程语言没法比的。

✅ 第一章 自检清单
  • 我能否清晰解释“数据流驱动”与“顺序驱动”在代码执行逻辑上的根本区别?
  • 我是否掌握了 LabVIEW 的核心学习三部曲(路线图、理论知识、实战练习)?

第二章 基础数据类型解析

💡 本章导读

LabVIEW 支持多种数据类型,包括标量(布尔、数值、字符串)和结构化类型(数组、簇),并通过多态性简化了数据类型的管理。多态性允许函数适应不同类型的输入数据。本章将详细解析五大核心数据类型的操作方法,以及“类型定义”在大型项目重构中的重要作用。

LabVIEW 支持多种数据类型,包括标量和结构化类型,并通过多态性简化了数据类型的管理。多态性允许函数适应不同类型的输入数据,尽管普通虚拟仪器(VIs)在某些类型间的适应性有限。LabVIEW2017 引入了延展性 VIs,进一步增强了多态性。

2.1 布尔 (Boolean)

💡 核心摘要
  1. 主要内容:Bool 是什么?是 1 与 0,是 Yes 与 No,还是 True 与 Fail,它都是,Bool 是两种状态而已。非黑即白的两个状态表示。但在计算机中布尔值并不是一个 bit,而是一个字节 Byte。用 8 位二进制表示的。只有当其中所有的位都是 0,输出才是 0。
UntitledUntitled

Bool 是什么?是 1 与 0,是 Yes 与 No,还是 True 与 Fail,它都是,Bool 是两种状态而已。非黑即白的两个状态表示。但在计算机中布尔值并不是一个 bit,而是一个字节 Byte。用 8 位二进制表示的。只有当其中所有的位都是 0,输出才是 0。

z144-4bc6c0d66c4e3a032046192d3c266a82.pngz144-4bc6c0d66c4e3a032046192d3c266a82.png

NaN 与任何数都不相等,包括它自己。如果要检查一个数据是否是 NaN 只能使用“不是一个数字/路径/引用”函数来检查:

UntitledUntitled

布尔控件从外观上来看,是各种样式的开关、按钮和灯泡:

UntitledUntitled

其中,前两个机械动作模拟开关,每次点击,状态就会发生改变:开变关,关变开;

后四个机械动作模拟按钮,按下再松开手,按钮会自动恢复默认状态。开关或按钮按下是一个持续的动作,有一个过程,但布尔数值,就两个状态,这六种机械动作就定义了,在按下控件的过程中时,究竟何时改变控件的值。

最符合用户习惯的设置是,对于开关类型的控件,选择第一种机械动作,即,每次鼠标按下就立即切换数据的值;

对于按钮类型控件,选择第二排第二列的机械动作,即每次鼠标按键放开时,发出一个值改变的脉冲信号。所谓脉冲信号是指,按钮控件的布尔数值原本是 False,在鼠标按键放开的瞬间变为 True,然后立即恢复为 False。

在大多数程序中,按钮常常被用来触发一个事件,去处理某个工作。关于这一点,后文还会在事件结构中继续讨论。在后面的章节中,会讲到如何使用控件的局部变量和“值”属性节点。对于大多数控件而言,除了可以通过它们的接线端读写数据以外,还可以通过它们的局部变量 and “值”属性节点读写数据。但是,机械动作为触发型的布尔控件,也就是第二排的三种机械动作类的布尔控件,是不能够使用局部变量和“值”属性节点的。

⚠️ 技术避坑提示

注意:在 LabVIEW 中,若布尔控件的机械动作被设定为触发型(如:释放时触发、按下时触发或双态触发),由于其内部的值是依靠物理事件发生后瞬时切换并立刻自动复位(类似于按钮的脉冲信号),因此在软件层面上是绝对无法为其创建“局部变量”或“值”属性节点的(在右键菜单中会变灰不可选;强行连线会产生 Broken Run 红色断线报错)。若程序架构中确实需要通过变量对布尔值进行读写,必须改用开关型机械动作。

2.2 数值 (Numeric)

💡 核心摘要
  1. 主要内容:双精度浮点数(Double),单精度浮点数(Single),32 位/64 位有符号长整形和无符号长整形等;在程序中表征的颜色为橙色或者蓝色。数值中不同的类型,表示其代表的数据精度不同,也表示在计算机内存中所占用的空间不同。

双精度浮点数(Double),单精度浮点数(Single),32 位/64 位有符号长整形和无符号长整形等;在程序中表征的颜色为橙色或者蓝色。数值中不同的类型,表示其代表的数据精度不同,也表示在计算机内存中所占用的空间不同。

控件

UntitledUntitled

虽然在前面板上的外观各不相同,但是它们所表示的数据类型是相同的,都属于数值类型。选板右上方两个控件的数据类型是“时间”,也是数值数据的一种显示方式。还有其它一些控件,尽管位于别的选板,但它们的数据类型也是数值型的,比如下拉列表控件、列表框控件等。

数据格式

一个数值型数据还可以有多种不同的表示法,用来表示不同范围和精度的数据。我们可以认为数值类型属于一种数据类型,而 I32,U8 等只是不同的表示法;也可以把数值类型的不同表示法视作不同数据类型。在文本编程语言中,一般都是把 I32,U8 等当作不同的数据类型处理的。

在 VI 的前面板上放置一个数值型控件,或在程序框图上放置一个数值常量,在它们的右键菜单中可以查看或更改其表示法(Representation):

UntitledUntitled

在 LabVIEW 帮助的索引中搜索“数值”,打开数值分类下的数据,可以查看到每种表示法的详细解释。从表示法的图标中可以很清楚地看出,每种表示法的区别在于数据长度不同。计算机使用的是二进制,每一位可以表示 0 或 1 两个值,8 位为 1 字节。每种表示法的长度如下表所示。

EXT 扩展精度实数,16 字节长 DBL 双精度实数,8 字节长
SGL 单精度实数,4 字节长 FXP 定点数,最大 8 字节长
I64 带符号 64 位整数 I32 带符号 32 位整数
I16 带符号 16 位整数 I8 带符号 8 位整数
U64 无符号 64 位整数 U32 无符号 32 位整数
U16 无符号 16 位整数 U8 无符号 8 位整数
CXT 扩展精度复数,2×16 字节长 CDB 双精度复数,2×8 字节长
CSG 单精度复数,2×4 字节长

一般来说,长度越长,可以表示的数值范围就越大、精度也越高,但计算速度越慢,占用存储空间也越大。

选择表示法首先要考虑能够满足程序需求。比如说 I16 表示法能够支持的数值范围是 - 32768 到 32767 之间的整数,这个范围甚至不够计算 300×300 这样的简单算术运算。我们不妨现在就编写一个程序:新建一个 VI,在 VI 上放置两个值为 300 的 I16 常量,然后相乘,将乘积用一个 I16 的数值控件来显示,看看他们的积是多少。将会是 24464,而不是 90000。这种错误叫做“溢出”,也就是需要表示的数值已经大于一个控件可以表示的最大数值了。此类错误如果隐藏在一个大工程内,查找起来是颇为困难的。

UntitledUntitled

函数

与数值数据相关的基本运算函数和节点大多位于“编程 -> 数值”函数选板下:

UntitledUntitled

这些函数节点的图标非常直观地表示出了它们的功能:加、减、四舍五入、求倒数等。在“数学”函数选板中,还有一些更复杂的有关数学运算的函数和 VI。每一个函数的功能可以在 LabVIEW 帮助文档上找到

表达式节点

UntitledUntitled

公式 Express VI

UntitledUntitled
UntitledUntitled

公式节点

对于多输入多输出或更加复杂的计算,可以使用公式节点(在函数选板“编程 -> 结构”上):

UntitledUntitled

用户可以把它看作是更为复杂的支持多输入输出的表达式节点。公式节点中的表达式语法与 C 语言类似,相当于实现了一个只包含基础的数学运算的 C 语言的子集。熟悉 C 语言的用户,使用公式节点不会感到陌生。对于没有 C 语言经验的读者,需要先学习一下 C 语言的基本语法,这样可以帮助快速使用公式节点。

在使用公式节点的时候,如果一个变量表示的是输入值,则不需要在公式节点内进行声明,比如上图程序中的变量 a 和 x,它们的类型定义是在输入控件中定义的。文本程序中的其它变量,一定要预先声明,这也是 C 语言的语法之一,比如上图程序中的 y 和 temp,需要在程序开头声明它们的数据类型是 int32。

2.3 字符串 (String)

💡 核心摘要
  1. 主要内容:LabVIEW 中字符串的存储方式与 C 语言相类似,都是使用表示法为 U8 的数值数组。二者的区别在于,C 语言中的字符串以字符 “\0” 作为字符串结束标志,而 LabVIEW 的字符串还记录了长度信息,不需要再使用特殊的结束符。

LabVIEW 中字符串的存储方式与 C 语言相类似,都是使用表示法为 U8 的数值数组。二者的区别在于,C 语言中的字符串以字符 “\0” 作为字符串结束标志,而 LabVIEW 的字符串还记录了长度信息,不需要再使用特殊的结束符。

因为字符串数据在内存中存储数据的方式与 U8 数组相同,所以这两种数据之间的类型转换是有实际意义的。转换成的 U8 数组中每个元素是字符串中每个字母的 ASCII 码,使用十六进制显示字符串时,看到的也是字符串中每个字符的 ASCII 码。不过 LabVIEW 已经提供了专门在字符串与 U8 数组之间转换的函数:“字符串至字节数组转换”和“字节数组至字符串转换”,不必使用强制类型转换函数。下图中的两种转换方式是完全等效的。

UntitledUntitled

字符串控件

LabVIEW 的字符串控件除了具有正常的显示方法之外,还提供了另外三种非常有用的显示方式:“’' 代码显示”、“十六进制显示”以及“密码显示”方式:

UntitledUntitled

字符串中,有些字符具有特殊含义或无法显示,比如回车、换行等符号。这时,可以使用“’' 代码显示”方式,把不能显示的字符用 ’' 转义代码表示出来。对于使用过文本编程语言的程序员来说 ’' 转义符不会陌生,C 语言中使用同样的转义符来表示字符串中的特殊字符。在 LabVIEW 中,最常用的转义符就只有 “\n” 表示换行符、“\r” 表示回车符、“\t” 表示制表符、“\s” 表示空格、“\” 表示 ’' 等几个。

数值、时间与字符串之间的转换

UntitledUntitled

大部分字符串函数的用法,比如计算字符串长度、合并字符串等,都比较直观,基本上拿来就可以用。

扫描字符串与格式化写入字符串
UntitledUntitled
字符串公式求值

再看一个具体的示例程序:字符串公式求值。程序要求输入一个字符串,用于表达一段简单的数学公式,比如“sin (pi (1/2)) + 3*5 - 2”;以实数形式输出这个公式计算后的值。

之前提到的公式 Express VI 和公式节点都只能在程序编辑时设置固定的公式;程序运行后,就只能改变参数,不能再改变公式本身了。

“数学 -> 脚本与公式 -> 一维二维分析 -> 字符串公式求值”VI

UntitledUntitled

2.4 数组 (Array)

💡 核心摘要
  1. 主要内容:数组也是一种复合数据类型,与簇数据类型不同的是:一个数组中所有的元素的数据类型都必须是同一种。创建数组控件(或常量)与创建簇控件非常类似,首先把只有一个空壳的数组控件拖到前面板上,再把其它某个控件拖入数组控件即可,LabVIEW 中几乎任何其它数据类型都可以作为数组元素的数据类型,但数组本身不能作为…

数组也是一种复合数据类型,与簇数据类型不同的是:一个数组中所有的元素的数据类型都必须是同一种。创建数组控件(或常量)与创建簇控件非常类似,首先把只有一个空壳的数组控件拖到前面板上,再把其它某个控件拖入数组控件即可,LabVIEW 中几乎任何其它数据类型都可以作为数组元素的数据类型,但数组本身不能作为另一个数组的元素

UntitledUntitled

数组元素的数据类型虽然是唯一的,但数据的个数可以是非常多的(理论上,每个维度可以最多包含

2^31-1 个元素)。数组控件左上角有一个额外的数字显示,它表示的是当前显示的数组元素的索引,也就是第几个元素。数组元素索引是从 0 开始计算的,第一个元素的索引是 0;第二个元素的索引是 1,以此类推。

数组数据的运算

数组的运算不难,但是是使用非常频繁。自己摸索即可。

UntitledUntitled

2.5 簇 (Cluster)

💡 核心摘要
  1. 主要内容:簇(Cluster)和之前介绍的数值布尔等简单数据类型不太一样,它是一类复合数据类型,它可以把多个不同类型的数据组织在一起,变成一个新的数据类型。簇和 C 语言中的结构(struct)、Python 语言中的元组(tuple)比较相似。

簇(Cluster)和之前介绍的数值布尔等简单数据类型不太一样,它是一类复合数据类型,它可以把多个不同类型的数据组织在一起,变成一个新的数据类型。簇和 C 语言中的结构(struct)、Python 语言中的元组(tuple)比较相似。

UntitledUntitled

簇控件和简单数据类型的控件也有明显区别,把它拖到前面板上,开始只是个空壳,不能使用。我们还要给簇添加其它一些数据类型作为它的“元素”,把其它控件拖入簇控件即可。簇是可以嵌套的:一个簇可以是另一个簇的元素。簇的常量的创建方式与控件的创建方式是类似的。

捆绑与解绑

UntitledUntitled

在程序中应尽量使用“按名称捆绑”和“按名称松绑”,而不是直接“捆绑”“松绑”。“按名称捆绑”和“按名称松绑”由于显示了元素的名称,不仅可读性比较好,还可以避免前后两个簇中元素顺序不一致等引发的错误:

2.6 类型定义与严格类型定义

💡 核心摘要
  1. 核心价值:利用自定义控件能够将数据类型集中管理,避免数据结构变更时引发的大范围程序断线。
  2. Type Def (类型定义):仅强制同步底层数据类型(如枚举元素、簇成员),保留本地外观与默认值的独立修改权。
  3. Strict Type Def (严格类型定义):强制 100% 同步数据类型及一切外观属性,常用于统一系统 UI 控件风格及保障属性节点调用的兼容性。

在 LabVIEW 编程中,当我们需要在不同的 VI 之间传递复杂的自定义数据(如枚举、配置簇)时,直接使用普通的控件极易导致后续的维护灾难。为此,LabVIEW 提供了 自定义控件(后缀为 .ctl 机制。

自定义控件有三种不同的模式:普通控件 (Control)类型定义 (Type Definition / Type Def)、与 严格类型定义 (Strict Type Definition)


1. 三种控制模式的区别

在自定义控件编辑窗口的工具栏下拉菜单中,可以自由切换这三种模式:

模式 核心同步范围 本地外观修改权 经典适用场景
普通控件 (Control) 无同步(仅作为一次性模版) 完全独立修改(已与原 .ctl 脱离) 仅仅用来保存一个精心美化的自定义外观控件模版。
类型定义 (Type Def) 仅同步底层数据类型 允许(可修改标签、颜色、默认值等) 状态机的“状态枚举”、数据传输的“配置参数簇”、全局变量载体。
严格类型定义 同步数据类型 + 所有外观属性 禁止(大小、颜色、字体内嵌被严格锁定) 主界面 UI 交互控件、统一风格的按钮与列表框、属性节点引用。

2. 普通自定义控件(Control)

  • 机制:类似于一个“复制-粘贴”模版。一旦将普通控件拖入主 VI 的前面板,它就会与原 .ctl 文件彻底切断联系。
  • 后果:今后若修改原 .ctl(如更改了簇中某个数值的范围),已经放置在主 VI 里的控件完全不会改变

3. 类型定义(Type Definition)

  • 机制:在类型定义模式下,主 VI 中所有调用了该控件的接线端,都与该 .ctl 保持强关联。
  • 数据类型强制同步:如果在 .ctl 文件中修改了数据类型(例如在枚举中添加了一个新状态,或往簇中增加了一个字符串字段)并保存,全项目中所有调用该控件的地方都会全自动同步更新,不会产生任何连线损坏。
  • 独立保留权:子 VI 依然可以自由修改本地的“标签名称”、“默认值”或“背景颜色”,这些个性化设置不会被原 .ctl 覆盖。

4. 严格类型定义(Strict Type Definition)

  • 机制:在类型定义的基础上,将外观属性同步权限收回。
  • 绝对一致性:不仅底层的数据类型同步,其控件大小、颜色、字体、甚至刻度显示等一切视觉外观,都严格受控于原 .ctl。在调用它的主 VI 中,除了控件的“标签名(Label)”外,其余所有外观设置都呈灰色锁定状态,无法在本地修改。
  • UI 级联控制:若需要为系统开发多套风格绝对一致的子界面,或通过属性节点(Property Node)对这些控件进行动态调用,严格类型定义是唯一的安全选择。

5. 工程防坑红线:为什么必须使用 Type Def?

在编写经典的**状态机(State Machine)**架构时,我们通常使用一个“枚举(Enum)”来保存所有程序状态(如 Init, Idle, Measure, Error, Exit)。

  • 错误做法(非 Type Def):直接在框图上右键创建一个普通枚举,并把它复制到了 10 个不同的子 VI 里。当程序需要拓展第 6 个状态时,由于原有的 10 个枚举没有统一源头,您必须手动逐个去添加修改,由于类型失联,程序框图会爆出数十处断线。
  • 正确做法:在编写第一个状态机前,必须将该枚举保存为 .ctl 控件并设为 Type Definition。后续无论增加多少个状态,只需双击打开 .ctl 一处修改保存,全程序瞬间完成平滑升级。
✅ 第二章 自检清单
  • 我是否掌握了数值类型(双精度、整型)的转换规则,以及如何避免精度流失?
  • 我能否区分“簇(Cluster)”与“数组(Array)”在数据维度和元素类型上的区别?
  • 我是否理解了“类型定义(Type Def)”与“严格类型定义”在更新控件外观和数据结构时的传播机制?

第三章 控制结构与循环控制

💡 本章导读

控制结构是流程逻辑控制的工具。在 G 代码中,While 循环、For 循环、条件结构、事件结构和顺序结构等通过图形化的框架边框体现。如何利用这些结构进行有效控制,并使用移位寄存器在循环间安全传递变量,是编写可靠程序的核心技能。

3.1 While 循环

💡 核心摘要
  1. 主要内容:While 循环用于重复执行内部代码,其退出逻辑由条件终端(真时停止/假时停止)决定,每次循环至少执行一次。
  2. 内存特性:在单次迭代的 While 循环中使用未初始化的移位寄存器,可以用于在 VI 调用间保持数据状态,这是功能全局变量 (FGV) 的核心实现原理。
  3. 工程规范:在工控开发中避免使用强行中止按钮,必须为 While 循环提供合理的软件停止开关和合理的延时以防止 CPU 占满。
UntitledUntitled

While 循环是 LabVIEW 中最常用的结构之一。它可以重复执行框图内部的代码,直到布尔条件终端的逻辑状态触发退出。

在条件终端上右键,可以选择 真时停止 (Stop If True)假时停止 (Stop If False) 两种退出策略。由于 While 循环是先执行后判断,因此无论如何其内部代码都至少会执行一次

1. 未初始化移位寄存器的状态保持

如果在一个仅执行一次的 While 循环中使用未初始化的移位寄存器,该寄存器在 VI 被重复调用时将保留上一次的运行值。利用该内存特性,可以方便地构建用于保存状态信息的子 VI(例如在多次调用间计算时间差,或实现经典的 功能全局变量、功能全局Vi|功能全局变量 (FGV))。

2. 避免编写失控的无限循环

在工业测控程序中,绝不应该编写无法由软件受控停止的无限循环。通过工具栏中的“中止 (Abort)”按钮强行终止 VI 运行是极其危险的,因为这会跳过析构和释放过程,导致外部 I/O 硬件处于不确定的非安全状态。 因此,合格的工程规范要求:

  • 必须在前面板上为 While 循环绑定一个布尔“停止”按钮,并连接到条件终端。
  • 必须在循环内添加微小的延时函数(如 Wait (ms)),防止循环空转占满 CPU 线程。
数据依赖与停止响应延迟数据依赖与停止响应延迟

3. 数据依赖与响应延迟问题

如上图所示,当 While 循环内的逻辑非常复杂且缺乏数据依赖时,停止开关的布尔状态可能会在循环其他逻辑执行完毕之前就被提前读取。如果此时用户按下停止,由于条件已被判定,循环仍会强制完整执行完这一个周期后才退出。若单个循环周期执行耗时较长,就会产生明显的响应滞后感。

3.2 For 循环

💡 核心摘要
  1. 主要内容:对于循环非常适合构建和处理数组以及重复固定次数的操作。大多数情况下,你使用 For 循环处理数组,因为 LabVIEW 已经知道数组中有多少个元素,自动索引功能会自动为你处理迭代次数:你所要做的只是将数组连线到循环,迭代次数(计数)将会等于数组中的元素数量。
UntitledUntitled

对于循环非常适合构建和处理数组以及重复固定次数的操作。大多数情况下,你使用 For 循环处理数组,因为 LabVIEW 已经知道数组中有多少个元素,自动索引功能会自动为你处理迭代次数:你所要做的只是将数组连线到循环,迭代次数(计数)将会等于数组中的元素数量。

输入隧道

数据线通过循环结构边框时,会在边框上形成一个颜色与数据线相同的小矩形(有实心的,也有空心的)。这个小矩形叫做隧道,负责把数据传进或传出结构。在其它结构中,也都有隧道,它们的功能十分类似。根据数据进出结构的方向,隧道可以分为输入隧道和输出隧道:输入隧道的输入端在结构外侧,输出端在结构内侧;输出隧道的输入端在结构内侧,输出端在结构外侧。

如果是单个数据进入循环结构,隧道会是一个实心小矩形,循环每次迭代都会读入同一个输入数据。如果输入的数据是一个数组,循环结构可以使用一种独特的方式,让隧道具备索引功能。开启了索引功能的隧道,每次循环迭代依次取出结构外数组的一个元素。这相当于把隧道和索引数组的功能结合起来了。索引隧道的外观是一个空心的小矩形。在隧道的右键菜单中,可以选择“禁用索引”或“启用索引”,以禁用或启用隧道的索引功能。

使用了索引隧道的 For 循环结构,可以不用提供循环次数,即不必输入 N 值,循环迭代次数由输入数组的长度决定。迭代次数即数组长度。这样,循环结构恰好能够处理完输入数组的每一个元素。

UntitledUntitled

规则:较小的计数总是优先。如果空数组连接到了 For 循环,该循环将永远不会执行。

输出隧道

对于循环结构的输出隧道来说,它的输入端在循环结构之内,也就是说每次循环迭代都会传递给隧道一个数据;而隧道的输出端只有一个值。因此,循环结构的输出隧道要负责把输入的多个数据合并整理成为一个单个的数据,传递出去。我们可以给输出隧道设置不同的数据合并方式,在它的右键菜单上可以看到,它有三种模式:

  • 最终值: 图标是一个实心方块。这种模式只输出最后一次循环迭代传递给隧道的数据。
  • 索引: 图标是一个空心方块。与输入隧道的索引模式先对应,把每一次循环迭代传递给隧道的数据作为数组元素,合并成一个数组传递出去。如果输入的数据已经是数组了,那么就会把输入数组增加一个维度输出。
  • 连接: 图标是一个带横条纹的方块。这种模式只能应用于隧道的输入端数据的类型是数组类型的情况。与 Indexing 不同的是,输出的数组与输入数组维度相同,但是长度增加了。每一次循环迭代传递给隧道的数组,会被追加到输出数组的后面。
UntitledUntitled

除了以上的三种模式,还可以为输出隧道添加一个条件输入(Conditional),具有条件输入的隧道会多一个图标为问号的接线端。可以输入一个布尔值,如果输入的值为“真”,则输入数据会被保留;如果输入值为“假”,则输入数据会被忽略,不会出现在隧道的输出端。

3.3 条件结构

💡 核心摘要
  1. 主要内容:条件结构简单好理解,没有什么乱七八糟的操作。但是结合 While 循环,可以组成 常用的状态机结构,可以参考后续内容学习。
UntitledUntitled

条件结构简单好理解,没有什么乱七八糟的操作。但是结合 While 循环,可以组成 常用的状态机结构,可以参考后续内容学习。

image-20240716091126-gbu5ssz.pngimage-20240716091126-gbu5ssz.png
image-20240716091143-8mwnipz.pngimage-20240716091143-8mwnipz.png

3.4 事件结构

💡 核心摘要
  1. 主要内容:事件结构相当于中断,当满足一些事件的时候,就会执行对应框图中的东西。经常配合 While 循环使用,用户的很多功能都是通过 While 循环加上事件结构实现的。也非常好理解,难点是后续将 While 循环,事件,条件结合组成框架的灵活使用,将会在 LabVIEW 中级阶段学习。本阶段主要针对事件对基础控件的响应操作…

image-20240712111303-wy8519x.pngimage-20240712111303-wy8519x.png

事件结构相当于中断,当满足一些事件的时候,就会执行对应框图中的东西。经常配合 While 循环使用,用户的很多功能都是通过 While 循环加上事件结构实现的。也非常好理解,难点是后续将 While 循环,事件,条件结合组成框架的灵活使用,将会在 LabVIEW 中级阶段学习。本阶段主要针对事件对基础控件的响应操作。

3.5 顺序结构

💡 核心摘要
  1. 主要内容:顺序结构是 LabVIEW 独有的结构。看起来像电影的一帧一帧的胶片的样子,发明的灵感也是来源如此。功能就是内容从左往右的执行,执行完框中所有的内容才会执行下一步。
UntitledUntitled

顺序结构是 LabVIEW 独有的结构。看起来像电影的一帧一帧的胶片的样子,发明的灵感也是来源如此。功能就是内容从左往右的执行,执行完框中所有的内容才会执行下一步。

UntitledUntitled

鼠标右击,可以进行随意创建帧,也可以替换成层叠式,就是垂直落到一起。功能是一样的,只是样子变化。

3.6 移位寄存器

💡 核心摘要
  1. 主要内容:移位寄存器是在 For 循环和 While 循环中可用的特殊局部变量或存储器元件,它将值从一次迭代的完成转移到下一次迭代的开始。 您可以通过在循环的边界上弹出来创建它们。 当循环的迭代完成后,一个值被写入移位寄存器-称它为第 n 个值。 在下一次迭代中,该值可用作数据源,现在称为(n–1)st 值。 此…

移位寄存器是在 For 循环和 While 循环中可用的特殊局部变量或存储器元件,它将值从一次迭代的完成转移到下一次迭代的开始。 您可以通过在循环的边界上弹出来创建它们。 当循环的迭代完成后,一个值被写入移位寄存器-称它为第 n 个值。 在下一次迭代中,该值可用作数据源,现在称为(n–1)st 值。 此外,您可以在左侧添加任意数量的终端,从而不仅返回(n–1)st 值,还返回 n–2,n–3 等。 这使您能够进行数字滤波,离散系统建模以及其他需要某些变量值的简短历史记录的算法。 任何类型的数据都可以存储在移位寄存器中-它们是多态的。

 一个简单的移位寄存器的实现 一个简单的移位寄存器的实现

一个简单的移位寄存器的实现

构建数组连接新元素,直到达到大小构建数组连接新元素,直到达到大小

构建数组连接新元素,直到达到大小

旋转数组将数组移位-1 个元素,然后替换数组子集用最新的元素复盖最旧的元素。旋转数组将数组移位-1 个元素,然后替换数组子集用最新的元素复盖最旧的元素。

旋转数组将数组移位-1 个元素,然后替换数组子集用最新的元素复盖最旧的元素。

用移位寄存器清除空字符串,并初始化默认配置用移位寄存器清除空字符串,并初始化默认配置

用移位寄存器清除空字符串,并初始化默认配置

✅ 第三章 自检清单
  • 我能否区分 While 循环中“移位寄存器(Shift Register)”与“普通通道”在数据传递上的差异?
  • 在 For 循环中,自动索引(Auto-indexing)是如何工作的?在什么情况下应该手动关闭它?
  • 为什么在大型响应式 UI 架构中要优先使用事件结构,而不是用 While 循环持续空转轮询?

第四章 数据传输、变量与子 VI 封装

💡 本章导读

随着程序规模的扩大,模块化和变量管理变得至关重要。本章将学习如何通过属性节点和方法动态控制 UI 界面,理解局部变量与全局变量的使用场景及其潜在的内存竞争风险,并掌握创建高内聚、低耦合子 VI(SubVI)的接线板分配规范。

4.1 属性节点与方法

💡 核心摘要
  1. 核心机制:属性节点(Property Node)用于在程序框图中读取或修改前面板控件的各种属性(如可见性、禁用状态、颜色等)。
  2. 绑定方式:分为隐式绑定的静态属性节点(直接右键创建,仅限本地 VI 内部使用)与显式绑定的动态属性节点(通过控件引用传递,可在子 VI 中复用)。
  3. 性能红线:属性节点运行在 UI 线程中,具有极高的线程切换与渲染开销。严禁在高速循环内使用属性节点,尤其是极度消耗性能的 Value(值)属性。

1. 属性节点的基本分类

在前面板控件上右键选择 创建 -> 属性节点,即可快速生成一个属性节点。属性节点主要分为以下两种使用模式:

  • 静态隐式绑定:直接从本地控件创建。该节点直接与控件绑定,不需要在程序框图上连接任何引用(Reference)端子。其缺点是只能在其所在的当前 VI 内部操作前面板对象,无法跨 VI 传递。
  • 动态显式绑定:通过控件引用(Control Reference)端子传入。这种模式允许将控件的引用作为参数传递给子 VI(SubVI),并在子 VI 内部操作调用方前面板上的控件属性。这是开发可重用 UI 框架(如多窗口管理、动态参数配置)的核心手段。
静态链接和动态链接的属性节点静态链接和动态链接的属性节点

2. 操作规范与多属性组合

  • 每个控件和指示器都拥有一组丰富的属性列表(如 VisibleDisabledBlinking 等)。
  • 节点展开:将鼠标悬停在属性节点的底部边缘,向下拖动,可以一次性读写多个属性。
  • 执行顺序:单个属性节点内的所有属性读取或写入,在运行时是严格自上而下顺序执行的。
  • 读写转换:对节点内的每个属性分支,均可以右键选择“转换为读取”或“转换为写入”进行独立控制。

3. 性能与内存优化(防坑红线)

  • UI 线程阻塞开销:属性节点的执行必须在 LabVIEW 的用户界面(UI)线程中同步进行。在高速数据处理循环内频繁调用属性节点,会因为强行进行线程上下文切换(Context Switch)和界面渲染,导致系统响应严重卡顿。
    • 规范建议:永远不要在后台的高速数据采集或处理循环中放置属性节点。应当将数据计算与 UI 界面交互拆分,使用独立的 UI 消息循环(如生产者-消费者架构中的消费者循环)与前面板进行隔离交互。
  • 前面板内存常驻问题:如果在子 VI 中直接放置了对应子 VI 前面板控件的属性节点,会导致该子 VI 被调用时,其前面板(Front Panel)被迫加载到系统内存中,产生不必要的内存开销。在开发大规模应用时,建议通过显式控件引用传递进行解耦。
  • 规避使用 Value 属性

    [!WARNING] 性能警告 属性节点中的 Value(值) 属性是一个极其消耗系统性能的“性能消耗大户(Performance Hog)”。它不仅会触发 UI 刷新,还会产生数据拷贝与同步开销。 进行前面板控件数据传递时,请优先使用接线端直接连线局部变量。只有在必须进行跨线程强同步刷新、或是在动态调用子 VI 赋值时,才允许极少数地使用 Value 属性。

4.2 局部变量与全局变量

💡 核心摘要
  1. 局部变量:用于在单个 VI 内部实现对同一个输入/显示控件的跨位置读写,绕过了严格的数据流连线,但会产生额外的内存副本与线程切换开销。
  2. 全局变量:用于跨 VI 传递数据。内置全局变量仅能存储数据;而基于 SubVI 的功能全局变量(FGV)可封装业务算法。
  3. 安全风险:多处写入全局/局部变量会破坏数据流的确定性,引发竞态条件(Race Condition)。应严格遵循“单写多读”原则。

1. 局部变量 (Local Variables)

局部变量允许在单个 VI 的范围内绕过连线直接读写数据。您可以在程序框图的多个位置,对同一个前面板输入控件(Controls)或显示控件(Indicators)进行读取或写入。

1.1 局部变量的创建与机制

在前面板控件或程序框图接线端上右键点击,选择 创建 -> 局部变量 即可生成。局部变量有以下几个关键要点:

  • 作用域限制:局部变量仅作用于当前 VI 内部,无法跨 VI 访问其他前面板控件。
  • 数据副本与内存开销:局部变量的每个读取实例都会在内存中复制一份该控件的数据。对于大型数组或结构复杂的簇,频繁使用局部变量会导致大量的内存拷贝与性能损耗。
  • UI 线程上下文切换:与属性节点类似,在子 VI 中使用局部变量会导致其前面板被迫常驻内存,且在非 FPGA 平台上运行时会在用户界面(UI)线程与执行线程间产生频繁的上下文切换(Context Switch)。
  • 例外情况:在 LabVIEW FPGA 模块开发中,局部变量通常被直接映射为寄存器连线,不会产生额外的软件性能开销。

2. 全局变量 (Global Variables)

当需要在两个或多个独立的 VI 之间进行异步数据共享时,必须使用全局变量。在 LabVIEW 中主要有以下两种实现方式:

2.1 内置全局变量 vs. 功能全局变量 (FGV)

  • 内置全局变量:通过创建 .vi 全局变量文件实现。它仅提供纯粹的数据缓冲区,除了简单的数据读写外,无法在其中编写任何代码逻辑。它的优点是读取速度快,且支持多元素独立访问。
  • 功能全局变量 (FGV):通过在子 VI 中使用“While 循环(仅迭代一次)+ 未初始化移位寄存器”构建。FGV 支持将数据存取与具体业务逻辑(如初始化、读、写、递增、清空)封装在同一个子 VI 内部,保证了数据操作的线程安全(Atomic Operation)。

2.2 竞态条件 (Race Condition) 风险与防范

当两个或多个并行的循环/线程以不可预知的顺序读写同一个全局/局部变量,且程序的最终结果依赖于特定执行顺序时,就会产生竞态条件(又称竞争状态)。 这是初学者最容易犯的致命错误,由于破坏了数据流的先后约束,会导致程序在运行时随机出现不可重复的逻辑错误。

竞态条件示意图竞态条件示意图

防范竞态条件的黄金法则

  1. 单写多读 (WORM, Write Once Read Many):保证全局/局部变量在全程序中仅在一个位置进行写入(例如由专门的数据采集循环写入),而在其他并行循环中只进行读取操作。
  2. 强制执行顺序:通过错误连线(Error Cluster)或顺序结构,强制在全局变量完成初始化赋值之后,其他读取端才开始运行。
  3. 封装与互斥(功能全局变量):如果必须对全局数组进行修改(例如添加或替换元素),直接读写内置全局变量会产生大量的内存副本且极不安全。应当采用功能全局变量(FGV)将修改逻辑封装在子 VI 内部,从而保证整个读-改-写过程的原子性与单一内存开销。

2.3 最佳实践规范

⚡ > * **数据流优先**:仅在没有其他数据流连线替代方案时(如跨并行循环交互)才允许使用全局/局部变量。因为“连线太长”而图省事滥用变量,会严重破坏程序的易读性与可维护性。
  • 书签与定位:建议在框图上为每一个变量调用添加专门的标签注释(如 #GlobalConfigRead)。可以通过 视图 -> 书签管理器 快速列出全项目所有的变量操作实例;或通过在变量上右键选择 查找 -> 全局引用 来定位其全部调用位置。

4.3 子 VI(SubVI)的创建与接线规范

💡 核心摘要
  1. 封装优势:子 VI 能够极大提高代码的可重用性与可读性,将复杂的程序框图解耦。
  2. 接线红线(4-2-2-4 规范):统一遵循“左侧输入、右侧输出、下角留错”的标准,为数据流稳定性和统一风格打下工程基础。
  3. 图标规范:坚决避免使用系统默认的空白格子图标,必须使用“图标编辑器”制作直观的文本与图形简称。

子 VI(SubVI)的创建与接线规范

在 LabVIEW 编程中,子 VI(SubVI) 相当于其他文本语言中的“函数”或“方法”。合理地封装与规范地定义子 VI 接口,是编写整洁、易维护 G 代码的关键。


1. 为什么要使用子 VI

随着程序规模增大,主 VI 的程序框图(Block Diagram)极易变得极其庞大与混乱(俗称“面条代码”)。

  • 降低复杂度:将特定功能的代码块封装,使主程序框图一目了然。
  • 代码复用:一次编写,多次调用,避免重复造轮子。
  • 便于调试:可以将 bug 隔离在特定的子 VI 内部,单独测试。

2. 如何创建子 VI

在 LabVIEW 中有两种最常用的创建方法:

方法一:直接从框图部分封装(最快捷)
  1. 在主 VI 的程序框图上,使用鼠标框选需要封装的一组节点和连线。
  2. 点击菜单栏的 “编辑 (Edit) -> 创建子 VI (Create SubVI)”
  3. 系统会自动把该框选区域替换为一个子 VI 图标,并自动生成对应的接线映射。
  4. 双击打开该新图标,将其另存为有意义的文件名。
方法二:从空白 VI 手动搭建
  1. 创建一个全新的 VI,在其前面板(Front Panel)上布置好输入控件(Controls)和显示控件(Indicators)。
  2. 在右上角的**连接板(Connector Pane)**上,依次将前面板控件与连接板的小格子进行映射绑定(单击小格子,再单击控件)。

3. 4-2-2-4 标准连接板接线规范

为了让所有的子 VI 在主程序框图中看起来风格统一,并且连线不交叉,LabVIEW 社区及 NI 官方推荐使用 4-2-2-4(或 12 端子) 经典连接板布局。

!4-2-2-4连线规范示例 (示意布局:左 4、右 4、上 2、下 2)

3.1 连线面板端子划分法则
  • 左侧端子(输入参数):所有需要外界传入的输入参数,必须绑定在连接板的左侧格子
  • 右侧端子(输出参数):所有子 VI 运算完成需要传出的参数,必须绑定在连接板的右侧格子
  • 左下与右下端子(错误流,核心红线)
    • 左下角格:必须绑定 “错误输入 (Error In)” 簇。
    • 右下角格:必须绑定 “错误输出 (Error Out)” 簇。
    • 作用:这是控制 LabVIEW 数据流执行顺序的基石,即便该子 VI 内部不需要处理错误,也必须流转错误簇。
  • 上侧端子:通常预留给用于向下流转的“引用引用(Refnum)”或“类对象(Class Line)”。

原则:参数尽量靠近中线,错误簇稳居最下方,输入在左,输出在右。严禁颠倒输入输出方向。


4. 子 VI 的图标规范(拒绝空白默认图标)

默认创建的子 VI 图标都是一个带有一些数字的黄色空白方块。这会使得主 VI 的程序框图极其难以辨识。

  • 设计步骤
    1. 在子 VI 右上角的图标上双击,打开 “图标编辑器 (Icon Editor)”
    2. 使用底色工具为子 VI 填充符合其模块分类的颜色底板。
    3. 使用文本工具(Text)在图标中心写入 2-4 个英文字母或简短中文(如 OPEN, READ, INIT)。
    4. 可以引入图标库中自带的物理图标(如串口、文件、数学符号)。
  • 效果:精美的图标可以让任何阅读您程序框图的开发者,在不双击打开子 VI 的情况下,仅凭图标外观便一眼洞悉这行代码的业务逻辑。
✅ 第四章 自检清单
  • 为什么局部变量会导致程序中出现“竞态条件(Race Condition)”?该如何合理使用来规避风险?
  • 建立子 VI 时,我是否严格遵循了“左侧输入、右侧输出”以及“5-3-2-3”或“4-2-2-4”的接线端子物理排布规范?

第五章 G 代码排版美学与连线规范

💡 本章导读

图形化代码的排版美学直接决定了程序的可读性与后期维护难度。脏乱差的代码(如“面条线”、逆向流动、隐藏坏线)是开发过程中的灾难。本章将带你了解如何像写诗一样排版你的 G 代码,掌握“数据流向一致性”和“合理使用框图大小”的工程排版美学。

💡 核心摘要
  1. UI 规范:前面板控件风格统一,栅格对齐,坚持“左侧输入、右侧输出”的分布。
  2. 连线规范:数据流“严格自左向右”流转,严禁反向逆流或连线穿过控件背面。
  3. 框图整理:善用局部选择与快捷键 Ctrl + U 自动排版,为大型项目架构打下清晰的可读性底座。

图形化编程语言(G 代码)拥有极高的直观性,但若在编写时不遵守排版与对齐规范,极易生成难以维护、逻辑混淆的“面条代码”。良好的排版不仅可以减少逻辑 Bug,还能极大方便后续团队的协同开发。


1. 前面板(UI)排版美学规范

前面板是操作员与软件交互的窗口,排版应当简洁、对齐且色彩协调:

  1. 控件风格保持绝对一致
    • LabVIEW 提供了银色(Silver)、经典(Classic)、现代(Modern)以及系统(System)等多套外观控件。
    • 红线:在一个软件前面板上,禁止混用不同风格的控件(例如,不要将一个银色按钮与一个经典数值框摆放在一起)。
  2. 栅格对齐与排布
    • 利用前面板工具栏的 “对齐 (Align)”“分布 (Distribute)” 按钮,确保多路控件边缘对齐、间距等分。
    • 遵循人类视觉习惯,输入控件(Controls)统一排在左边,显示控件(Indicators)统一排在右边

2. 程序框图(G 代码)连线金科玉律

连线代表了 LabVIEW 数据流的走向,是阅读程序逻辑的唯一通道:

2.1 严格自左向右(Left-to-Right Dataflow)
  • 所有数据线应当从左侧流向右侧
  • 严禁逆流:不要把数据线拉着转圈往左回折。如果必须回传数据,请使用“移位寄存器 (Shift Register)”或“反馈节点 (Feedback Node)”。
2.2 横平竖直,拒绝遮挡
  • 数据线折弯应当尽量呈 90 度,避免斜线和锯齿线。
  • 严禁穿过控件背面:连线必须绕过控件,禁止任何连线直接横穿过结构框(如 Case 结构、While 循环)或是控件的图标中心。
  • 拉开间距:当多根线平行排列时,应留出足够的空间,严禁多根不同的数据线紧贴重叠,这会导致排错时无法分辨。

3. 子 VI 接线板规范与错误流对齐

子 VI 的接线布局决定了主 VI 框图的连线干净程度:

  • 对齐流转:主程序框图里的“错误簇”连线,应当以一根平直的横线,穿过所有子 VI 底部左右端子:
  • 效果:这样会在整个程序框图的底部形成一条“错误防火墙通道”,当某个子 VI 出错时,错误信号会一平到底地向下传递,直观、清晰。

4. 自动整理工具的使用技巧

LabVIEW 内置了框图自动整理功能:

  • 快捷键 Ctrl + U:选中程序框图的某一区域(或不选代表全图),按下 Ctrl + U,LabVIEW 会自动帮您重整连线走向和控件位置。
  • 注意点:自动整理工具在处理简单结构时非常高效,但在面对超大型框图或有大量注释的复杂框架时,可能会破坏原本直观的物理布局。建议先手动规划好主框架分布(如大 While 循环位置),再局部选中连线密集的区域按下 Ctrl + U 进行微调。
✅ 第五章 自检清单
  • 我的代码是否符合“自左向右”的单一流动方向?是否存在从右向左的逆向连线?
  • 我是否养成了双击连线清理坏线、合理运用“整理程序框图(Clean Up Diagram)”工具辅助排版的习惯?

第六章 进阶显示:波形图表与图

💡 本章导读

在测控与工控行业中,实时波形展示是必不可少的核心需求。LabVIEW 提供了波形图表(Chart)、波形图(Graph)和 XY 图(XY Graph)等多种高级显示控件。本章将详细对比这三者在数据缓存机制、接收数据格式以及适用场景上的根本区别。

6.1 波形图表

💡 核心摘要
  1. 主要内容:能够方便的把数据以图形化的方式展现出来,是 LabVIEW 的一大特色。 LabVIEW 为此提供了丰富的控件和函数,可以大大简化图形化显示数据的复杂度。LabVIEW 图形控件选板上列出了几十种控件,分别用于显示不同类型的数据。但实际上,真正用于显示的部分,不需要分成那么多种控件,比如,一…
UntitledUntitled

能够方便的把数据以图形化的方式展现出来,是 LabVIEW 的一大特色。 LabVIEW 为此提供了丰富的控件和函数,可以大大简化图形化显示数据的复杂度。LabVIEW 图形控件选板上列出了几十种控件,分别用于显示不同类型的数据。但实际上,真正用于显示的部分,不需要分成那么多种控件,比如,一个图片控件既可以显示用直角坐标系表示数据,也可以显示用极坐标系表示的数据。

UntitledUntitled

波形图表,默认的输入是浮点数,他是自带历史缓存的波形显示工具,他的横坐标是数量,纵坐标是输入的浮点数。

UntitledUntitled

如果想显示多条曲线,只需要输入二维数组即可。

6.2 波形图

💡 核心摘要
  1. 主要内容:波形图表,默认的输入是数组,他是没有缓存的波形显示工具
UntitledUntitled

波形图表,默认的输入是数组,他是没有缓存的波形显示工具

UntitledUntitled

因为波形图的横坐标默认的是时间,输入的一维数组是幅值。

UntitledUntitled

到目前为止,我们一直在使用数组的索引来表示曲线的时间信息,但在很多实际应用中,是需要显示曲线的实际时间信息的。比如,如果一段数据采集于 2021 年 12 月 18 日上午 9 点 01 分 01 秒至 2021 年 12 月 18 日上午 9 点 01 分 02 秒,这些时间信息需要被显示在波形图的横轴上以方便用户理解数据。这就需要把时间信息和数据的值一同传递给波形控件才行。在 LabVIEW 中,我们可以把时间信息和波形数据一起打包成一个簇。不过,我们不需要自己定义这个簇了,LabVIEW 已经定义了一个特殊的簇类型,专用于保存待时间的波形数据,这就是波形数据类型。

波形数据类型包含四个元素:t0(采样起始时间)、dt(采样间隔时间)、Y(数据,一维数组表示的每个点对应 Y 轴上的值)、attributes(波形的一些属性)。由于波形包含的信息多于单纯的数组,所以程序中应当尽量以波形数据类型来表示采集到的数据。有关波形数据的函数都在 LabVIEW 的函数选板的 “编程 -> 波形” 中。

下图中的程序生成了一个波形数据。它使用系统当前的时间作为波形的起始时间,采样间隔是 0.1 秒。

6.3 XY 图

💡 核心摘要
  1. 主要内容:波形图控件处理的数据有一个特征,它的时间信号是有序等间隔的。对于这种数据,通常只需要用一个一维数组,表示每一个时间点上 Y 轴的数据即可。如果还需要具体的时间数据,也不需要把每个时间点的数据保存下来,只需要一个初始时间值,和一个间隔值即可。

波形图控件处理的数据有一个特征,它的时间信号是有序等间隔的。对于这种数据,通常只需要用一个一维数组,表示每一个时间点上 Y 轴的数据即可。如果还需要具体的时间数据,也不需要把每个时间点的数据保存下来,只需要一个初始时间值,和一个间隔值即可。

但是,有时候除了波形曲线,我们还需要绘制一些其他类型的曲线,它们的 X 轴可能并不是有序的,或者不是等间隔的。对于这样的数据,就还需要再增加一个一维数组,来表示数据在 X 轴上的每一个数值。这一类由一组对应的 X 和 Y 的值组成的数据,可以使用 XY 图形控件(XY Graph)来显示。

UntitledUntitled

我们通常会用 XY 图形数据来展现两组数据之间的关系。比如,在测控领域,常常用它来展示一组采集数据中两个通道的数据之间的关系;在数据统计或人工智能等领域,常常用它来展示一个数据集中,某个特征量的分布,或者两个特征之间的关系等。

XY 图的本质是描点。

✅ 第六章 自检清单
  • 波形图表(Chart)与波形图(Graph)的核心区别是什么?它们在内存中是如何存储历史数据的?
  • 绘制非等时间间隔的轨迹、圆环曲线或闭合路径时,为什么必须使用 XY 图?

第七章 数据存储与配置文件

💡 本章导读

工业测量数据需要持久化保存,配置信息也需要掉电保护。本章介绍如何在 LabVIEW 中实现文本文件、CSV 数据文件以及标准的 INI 配置文件(Configuration File)的读取与写入操作,为你搭建完整的本地存储与数据恢复逻辑。

💡 核心摘要
  1. 主要内容:LabVIEW 文件读写相关的函数和 VI 主要在“编程 -> 文件 I/O”函数选板上:

二进制文件和文本文件

LabVIEW 文件读写相关的函数和 VI 主要在“编程 -> 文件 I/O”函数选板上:

image-20240715114618-c1lpz4t.pngimage-20240715114618-c1lpz4t.png

可以把文件分为两大基础类别:二进制文件和文本文件。二进制文件中,每个字节的数据用 U8 整数表示的话,可以是 0~255 之间的任何一个数,当然在文件中,这个字节并不一定是用来表示整数的,它可能是用来表示其它数据类型的。文本文件中的每个字节则不会是任何数值,它们只会是某些人眼可读的字符所对应的二进制数值。比如,文件中会有大小写字母、数字、标点、空格、换行符等。如果用文本编辑器打开,文本文件是可以被直接阅读的,而二进制文件里通常只能看到一堆乱码。

文本文件读写

LabVIEW 还提供了“写入文本文件”和“读取文本文件”函数。在使用“写入文本文件”函数把字符串写入文件时,它会把字符串的内容写入文件。比如下面的程序:

image-20240715115443-liad4q4.pngimage-20240715115443-liad4q4.png

文件的读写遵循这三步法,第一步是打开,第二步是操作,最后是关闭。缺一不可。

ini 文件读写

其实与文本的读写是类似的。

image-20240715120403-laj3fr2.pngimage-20240715120403-laj3fr2.png

不同点在于,配置问卷的读取需要先规定数据的类型,因为 ini 文件时没有格式的,无法知道 ini 中的数据类型是什么?此外,这也是 ini 文件的优点,任意的数据类型都可以存储到 ini 文件中,并进行读取,这对于不常改变的配置参数的保存非常实用。

266f017c4e6f5fa5997ae7369cf33dbe266f017c4e6f5fa5997ae7369cf33dbe
✅ 第七章 自检清单
  • 在写入 INI 文件时,Section(小节)、Key(键名)与 Value(键值)是如何关联的?
  • 大批量、高频数据写入时,应如何避免因磁盘 IO 阻塞导致主程序界面卡顿?

第八章 程序控制基础:状态机结构

💡 本章导读

状态机(State Machine)是 LabVIEW 开发者必须熟练掌握的第一个标准设计模式。它通过“While 循环 + 条件结构 + 移位寄存器”的经典组合,将复杂的业务逻辑拆解为相互独立的状态分支。本章将带你编写一个高内聚、易扩展的标准状态机。

💡 核心摘要
  1. 主要内容:状态机结构
image-20240730092259-qcr0i1b.pngimage-20240730092259-qcr0i1b.png
image-20240730092712-d3e6cgg.pngimage-20240730092712-d3e6cgg.png
✅ 第八章 自检清单
  • 状态机的“状态选择”通常推荐使用什么数据类型?为什么使用“严格类型定义枚举”最为安全?
  • 我能否手绘出一个标准状态机的程序框图框架?

第九章 调试排错与分析技巧

💡 本章导读

程序开发中,90% 的时间都在与 Bug 搏斗。图形化编程有着其独特的调试工具。本章将带你掌握高亮执行(Highlight Execution)、单步调试、探针(Probe)以及条件探针的使用,让你能够精准捕捉每一根连线上的实时数据。

💡 核心摘要
  1. 图形化调试优势:LabVIEW 提供了极其直观的实时数据流可视化追踪手段。
  2. 核心工具链:包含高亮执行(小灯泡)、连线探针监控、断点挂起、以及单步步入步过等。
  3. 编译断线诊断:介绍快捷键 Ctrl+L(错误列表)作为静态排错的第一入口,快速定位连线类型不兼容。

LabVIEW 采用数据流(Dataflow)驱动机制。理解和掌握 LabVIEW 特有的图形化调试工具,可以帮助我们快速诊断逻辑漏洞与连线错误。


1. 四大核心图形化调试工具

在 G 代码程序框图的上方工具栏,分布着核心的调试按钮。

1.1 高亮执行(Execution Highlighting / 小灯泡)
  • 如何启用:点击工具栏上的 “小灯泡” 按钮使其变亮。
  • 行为表现:运行程序时,数据会化作一个个亮着的气泡,沿着数据线缓慢移动,并实时在气泡旁显示当前流经的数值。
  • 注意点:高亮执行会使程序运行速度下降数个数量级。它极适合用于观察 While 循环是否卡死,或者 Case 分支是否走错,但严禁在生产或测速环境中使用
1.2 探针工具(Probe Tool / 实时连线监控)

这是最常用、最高效的无损数据监控手段。

  • 如何使用:在程序框图的任意一根数据连线上,点击鼠标右键,选择 “探针 (Probe)”
  • 行为表现:系统会弹出一个探针小窗口。当程序运行时,每当有数据流过这根线,探针窗口就会立即更新并显示该数据的实时值(支持数值、字符串、甚至复杂的簇和错误流)。
  • 自定义探针:右键连线可以创建“自定义探针”,以图表或波形等可视化方式动态监测流动的数据。
1.3 断点(Breakpoints)
  • 如何设置:在工具选板中选取 “断点”工具(红点图标),在框图上的任意节点、循环或连线上单击;或右键连线选择 “设置断点”
  • 行为表现:程序运行到断点处会立刻自动暂停挂起,此时按钮栏的“单步调试”按钮会开始闪烁。此时,开发者可以使用探针观察四周的数据,确认无误后再点击“恢复运行”。
1.4 单步调试(Single Stepping)

在断点挂起或程序启动前,可以利用三个控制按钮进行微观单步执行:

  • 单步步入 (Step Into):若当前节点是一个子 VI,点击后会打开并进入该子 VI 内部,观察其内部数据流。
  • 单步步过 (Step Over):直接运行完当前节点,不进入子 VI 内部。
  • 单步步出 (Step Out):立即运行完当前子 VI 的剩余部分,返回上一层调用主 VI 框图。

2. 常见静态错误定位:断线与 Error List

当程序中存在语法错误(如未连线的端子、类型不匹配的数据线)时,工具栏左上角的“运行”按钮会裂开并变成一个灰色折断的箭头(Broken Run)。

2.1 快捷键 Ctrl + L:错误列表(Error List)
  • 当运行按钮折断时,直接按下 Ctrl + L(或者双击折断的运行按钮)。
  • 系统会弹出“错误列表”对话框,清晰列出当前项目里所有阻碍编译的错误条目。
  • 精确定位:选中某个错误条目,点击 “转至错误 (Show Error)” 按钮,LabVIEW 会自动在程序框图上高亮闪烁出错的节点或数据线,帮助我们瞬间定位。
2.2 常见的连线排错
  • 断线清理:使用快捷键 Ctrl + B 可以一次性清除全框图上所有因修改或残留产生的断线(废线),保持框图整洁。
  • 强制类型转换警告:如果连线上出现红色小三角(强制类型转换点),说明输入的数据类型与端子不完全一致(例如双精度浮点传给了整型),系统会自动开辟内存复制并转换。虽然不报错,但在循环中应尽量避免以节省内存。
✅ 第九章 自检清单
  • 当一条线段变红或断开时,通常代表什么错误?我该如何使用错误连线(Error Cluster)传播机制?
  • 探针工具(Probe)的作用是什么?如何在复杂数组或簇连线上添加自定义探针?

第十章 常见新手避坑指南(FAQ)

💡 核心摘要
  1. While 卡死:循环未加延时节点,导致 CPU 线程被榨干 100% 出现假死。
  2. Chart vs Graph:混淆了 Chart(自带历史缓存、接受单点)与 Graph(无缓存、接受数组一次性绘制)的根本差异。
  3. 变量滥用:在并行循环中多处写同一个局部变量,引发逻辑数据覆盖的“竞态条件 (Race Condition)”。

在初学 LabVIEW 开发的动手实操中,有几个非常普遍、被称为“新手杀手”的经典错误。提前了解并避免它们,可以节省大量的排错时间。


FAQ 1:我的 While 循环一跑就卡死,甚至前面板无响应?

  • 典型现象:程序点击运行后,鼠标变成沙漏,无法点击前面板的任何按钮,任务管理器中单核 CPU 占用率瞬间飙升至 100%。
  • 根本原因:在 While 循环内部,没有放置任何延时等待节点。CPU 以极限速度空转该 While 循环,直接榨干了系统时间片。
  • 解决方案
    • 在 While 循环框图内部,必须放置一个 “等待 (ms) / Wait (ms)”“等候下一个毫秒倍数 (Wait Until Next ms Multiple)” 节点。
    • 即使仅给定 1 ms10 ms 的等待时间,也能让 CPU 得到喘息,将系统占用率从 100% 一瞬间降到 1% 以下,前面板交互也会变得极其流畅。

FAQ 2:为什么我的波形曲线在图上只闪烁一个点,不画历史线?

  • 典型现象:做温度实时采集时,波形框里永远只看到最后一个温度值在第一列上下闪烁,没有向右延伸的历史走势曲线。
  • 根本原因:混淆了 波形图 (Waveform Graph)波形图表 (Waveform Chart) 的数据接收特性。
    • 波形图表 (Chart)自带内存数据缓冲区。您在循环里每采集到一个单点数值(如 25.4),直接连入 Chart 即可,它会自动帮您往后追加并滚动绘制历史线。
    • 波形图 (Graph)没有历史缓存。它每次接收一个完整的“数组”,并把这个数组的数据一次性重新渲染在屏幕上。如果在 While 循环中把单个数据点直接传给 Graph,它就会每次清空并只画那一个点。
  • 解决方案:做单点实时滚动显示时,右键前面板控件替换为 “波形图表 (Chart)”;如果是将采集完的整组历史数据绘制出来,请在 While 循环外部使用 “波形图 (Graph)” 接收引出的数组。

FAQ 3:子 VI 明明报错了,为什么主程序还在瞎跑?

  • 典型现象:下位机设备网线被拔掉或超时,子 VI 运行出错了,但是主程序没有弹窗、没有停机,还在继续后面的无效逻辑操作。
  • 根本原因错误线(Error Chain)发生了断路
  • 诊断方案
    • 检查程序框图,是不是在连接子 VI 时,漏掉了连接子 VI 底部的 “错误输入 (Error In)”“错误输出 (Error Out)” 端口。
    • 没有接错误线,子 VI 内部产生的错误就会在退出子 VI 的瞬间被直接“吞噬”,主程序全然不知,导致异常失控。
  • 规范做法:强迫自己用一根黄色的错误线把所有的子 VI 像穿糖葫芦一样穿起来,直达最外侧的错误捕获模块。

FAQ 4:为什么我的控件值被莫名其妙覆盖,修改了没反应?

  • 典型现象:在 While 循环 A 里修改了控件值,但 While 循环 B 运行后,这个值又自动弹回去了。
  • 根本原因过度滥用“局部变量 (Local Variable)”,导致了“竞态条件 (Race Condition)”
  • 诊断方案
    • 初学者图方便,喜欢在程序框图各处右键创建某个控件的“局部变量”,在多个不同的 While 循环或事件分支里同时往该变量写入数据
    • 因为多线程是并发执行的,此时哪个线程最后写入,控件就会显示哪个值,先写入的数据会被悄无声息地覆盖,造成数据混乱。
  • 工程防坑规范:严格遵守 LabVIEW 的数据流连线规则。如果需要在线程间传递数据,应当使用队列(Queue)全局变量(全局单点)功能全局 VI (FGV) 进行集中流转,严禁在多处并行地对同一个局部变量执行写入操作。
✅ 第十章 自检清单
  • 我是否已将本章列出的 10 大避坑条目(如避免滥用局部变量、及时释放资源、合理延时等)刻入开发习惯中?

第十一章 基础实践与试题自测

💡 本章导读

练习题来源于网络,不具备版权,仅供学习!通过嵌入试题,可以实现脱机情况下的内容自闭环。

💡 核心摘要
  1. 主要内容:Labview基础试题1

Labview基础试题1

Labview基础试题2

Labview-基础试题3

阶段一入门试题

Labview硬件试题

第十二章 结业实战:温湿度监控状态机系统

💡 本章导读

检验真理的唯一标准是实战。本章我们将结合前面学到的数据类型、移位寄存器、条件/事件结构、高级波形图表控件、INI 配置文件读写以及标准状态机框架,从零到一构建一个工业级的“温湿度监控状态机系统”。这不仅是你的入门结业作品,更是你迈向中高级开发的敲门砖。

💡 核心摘要
  1. 设计目的:将数据类型、While/Event 结构、移位寄存器、波形图表、文件 IO 与状态机框架深度串联融会贯通。
  2. 业务流程:温湿度模拟采集 ➔ 限值报警比对 ➔ 异常文本日志追加 ➔ 退出时自动加载/保存 ini 参数。
  3. 架构模式:采用标准状态机(State Machine),利用事件结构超时分支作为定时轮询触发源。

本实战项目作为 LabVIEW 入门培训的结业考核。通过动手独立完成该项目,学员能够将入门阶段学到的数据流、结构、文件 IO、UI 控件以及状态机框架有机串联,具备独立开发小型测控软件的能力。


1. 项目需求说明(做成什么样的软件)

我们需要为工业车间开发一套“温湿度实时监控软件”:

  • 1.1 动态仿真采集:系统无需物理硬件,每隔 500 ms 仿真生成一路环境温度(范围 1535℃)和一路湿度(范围 3080%)数据。
  • 1.2 UI 实时波形绘制:前面板使用“波形图表 (Chart)”实时滚动绘制两条曲线(红色代表温度、蓝色代表湿度)。
  • 1.3 报警监控与指示:用户可在前面板动态设定“温度上限”与“湿度上限”数值框。一旦仿真值超限,前面板对应的报警指示灯(LED)闪烁。
  • 1.4 报警文件记录 (File IO):一旦发生超限报警,系统应自动拼装格式化字符串,将 [当前时间戳] + [当前温湿度] + [报警类型] 追加写入本地的 alarm_log.txt 记事本文件中。
  • 1.5 ini 参数记忆
    • 软件启动时,自动从本地 config.ini 文件中读取上次保存的温湿度报警上限,加载到前面板。
    • 用户点击“退出”关机时,自动将前面板最新的报警上限写入 config.ini,实现记忆功能。

2. 系统框架设计:经典标准状态机

本项目强制学员使用 标准状态机 (State Machine) 架构开发。状态机由一个 While 循环 + 条件结构 (Case) + 移位寄存器 (Shift Register) 构成。

利用一个 类型定义 (Type Def) 的状态枚举 驱动状态流转,系统共设计 6 个状态:

graph TD
    INIT[1. Initialize 初始化] --> IDLE[2. Idle 等待响应]
    IDLE -- "超时 (500ms)" --> MEASURE[3. Measure 采集与判断]
    IDLE -- "点击退出" --> SAVE[5. Save 保存参数]
    MEASURE -- "正常" --> IDLE
    MEASURE -- "超限报警" --> ALERT[4. Alert 报警日志记录]
    ALERT --> IDLE
    SAVE --> EXIT[6. Exit 安全退出]

3. 各状态核心代码编写指导

3.1 Initialize(初始化状态)
  • 动作:调用“读取键值”VI,从 config.ini 读入 Temp_Limit(温度上限)与 Humi_Limit(湿度上限)的初值并绑定给前面板控件;初始化报警指示灯为 False。
  • 下一个状态Idle
3.2 Idle(空闲等待状态)
  • 动作:内部放置一个 事件结构 (Event Structure)
    • 分支一:超时事件 (Timeout):将超时时间设为 500(毫秒)。当学员没有操作时,每隔 500ms 触发一次超时,下一个状态设为 Measure
    • 分支二:退出按钮值改变:当用户点击退出,下一个状态设为 Save
    • 分支三:用户动态修改报警限值:捕获报警上限数值框的值改变事件,无需跳转,直接停留并更新移位寄存器中的限值。
3.3 Measure(采集与判断状态)
  • 动作
    • 利用“随机数 (0-1)”节点配合乘法与加法,仿真生成温湿度数据。
    • 使用“大于”比较节点,将采集值与移位寄存器中的报警限值进行比对。
    • 流转逻辑:如果有任一路超限,下一个状态设为 Alert 并将异常数据打包;若全部正常,下一个状态设为 Idle
3.4 Alert(报警日志记录状态)
  • 动作
    • 控制前面板对应的 LED 灯变红报警。
    • 调用 “格式化写入字符串 (Format Into String)”,将当前系统时间(Get Date/Time in Seconds)和温湿度仿真值格式化为:"2026-07-13 17:35:12, 温度 32℃ 超限报警!\n"
    • 调用“写入文本文件”VI(设置参数为 Append 追加写入模式),将该行字符串追加写入 D:\alarm_log.txt
  • 下一个状态Idle
3.5 Save(保存参数状态)
  • 动作:调用“写入键值”VI,将当前前面板控件里的温湿度报警限值作为参数保存到 config.ini 中。
  • 下一个状态Exit
3.6 Exit(退出状态)
  • 动作:将 While 循环的“停止接线端”置为 True,释放可能占用的文件句柄,安全结束 VI 运行。

附录 A:LabVIEW 核心术语中英文对照与高频快捷键

1. 核心术语对照表

中文术语 英文术语 说明
前面板 Front Panel 用户交互界面,包含控件和指示器。
程序框图 Block Diagram 后台代码逻辑区域,包含图标和连线。
控件 Control 前面板输入设备(如数值输入框、按钮)。
指示器 Indicator 前面板输出设备(如数值显示框、波形图)。
子 VI SubVI 相当于子函数,用于模块化封装。
Cluster 混合数据类型容器,相当于文本语言的 Struct。
移位寄存器 Shift Register 循环结构边框上的特殊端子,用于跨循环传递数据。
局部变量 Local Variable 用于在单个 VI 内部读写同一个前面板控件的数据。
竞态条件 Race Condition 两个以上的动作在未同步的情况下写入同一变量造成的错误。
状态机 State Machine 基于循环、条件分支和移位寄存器的标准程序框架。

2. 常用开发快捷键

快捷键 动作 用途
Ctrl + E 切换面板 快速在前/后面板之间来回切换。
Ctrl + H 开启/关闭即时帮助 鼠标悬停到任意函数上即可看中文提示,新手必备!
Ctrl + B 清理坏线 一键删除程序框图里断开或失效的虚线。
Ctrl + U 整理程序框图 让系统自动排版连线,可局部或全局使用。
Ctrl + R 运行 VI 启动当前程序。
Ctrl + . 终止 VI 强行终止正在运行的程序(注意:这会跳过析构,慎用)。
Ctrl + Space 快速定位 打开快速放置菜单,输入拼音或英文首字母即可搜索函数。
🔑
🔑 登录会员专享全本电子书

请先登录账号解锁全本阅读

本电子书为「G代码思维」登录用户免费专享,关注公众号回复【验证码】即可秒进登录解锁 12 大章节完整内容!

关注微信公众号「G 代码思维」回复【验证码】获取 4 位登录码
免费解锁 12 大章节、52 张高清架构示意图全本内容

💬 极客讨论区 (0)

欢迎发表技术见解、解耦思路或留言交流

🐻