精讲LabVIEW设计模式
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
状态机结构
对于一个最简单的状态机结构而言,它是 可以用顺序结构代替的;而对于相对复 杂的状态机结构而言,却可以作为测试 流程的组织者和管理者。
在LabVIEW下实现状态机结构
• While循环+Case结构 • 每一Case即为一个状态 • 当前状态中需有决定下一状态的判定代码 • 使用枚举常量通过移位寄存器传递至下一状态
精讲LabVIEW设计模式
LabVIEW 设计模式 LabVIEW 定时结构 优化LabVIEW程序内存管理 LabVIEW与多线程
调用动态链接库
什么是设计模式?
• 一种LabVIEW程序模板与架构
软件实践中通用的程序架构,其本质是对很多十分类似的问 题进行总结归纳的基础上提炼出的一些具有代表性的软件开 发规范
应用程序启动模式
1、SubVI目录 2、启动应用程序.vi 3、主程序“网络实验系统.vi”
代理模式
“我希望顶层VI(主VI)需要某个子VI时,才将其载入内存” “可以在应用程序中引入迟载入技术”
代理模式
总结
• 设计模式
– 简化LabVIEW开发过程 – 被广泛使用及证明其可用
• 常用的LabVIEW设计模式
在程序中动态调用子VI
——减少程序占用内存以及载入时间
ຫໍສະໝຸດ Baidu
• 打开VI引用 • 通过引用节点调用 • 关闭引用
1
2
3
配置 VI加载
1
2
数据类型转换
• 强制点表明连接了两种不同的数据类型
– LabVIEW中类型强制转换需要数据备份 – 涉及大数组的类型强制转换会占用大量内存
推荐的类型转换方式
• 更好的解决方式是在随机数创建时进行转换
用户界面事件的两种类型
通知事件 和 过滤事件
事件源:用户界面事件 用户自定义事件
5个函数
用户自定义事件DEMO
事件注册
静态事件注册:只有用户界面事件
选择事件源(程序、VI或控件)、特定事件、编辑 分支处理事件数据。Vi运行时自动注册。
动态事件注册:何时产生何种事件
静态事件注册demo
动态事件注册4个步骤
一个自定义的枚举类型对应一个状 态机中的状态集合
枚举常量举例
控件选板“Modern”
1、枚举控件、指示、常量
2、默认U16
3、修改 Edit Items
4、隐式与显式类型转换
DEMO1
顺序型状态机模式
数据传 递方式
DEMO2
改进的顺序型状态机模式
1、去掉i 2、添加一个移位寄存器
DEMO3
测试流程型状态机
– 避免转换大块数据缓存
(22.7 KB)
(14.3 KB)
把复杂VI分解成多个子VI
• 子vi会增加额外的前面板和框图的空间,但并 不增添额外的代码和数据空间。由于程序运行 时只有代码和数据被调入内存,子vi不会占用 额外的内存。
• 好处是子vi运行结束后,LabVIEW可以及时收回 子VI的数据空间,从而改善内存的使用效率。
1、数据通信采用全局变量、局域变量或共享变量; 2、Stop为Switch模式 3、有时会用到事件发生模块Occurrence
生产者/消费者
“我需要可以同时间执行的两个过程,并且需保 证它们不会互相影响执行速度。”
生产者/消费者
全局变量、局域变量或共享变量的每次复制都是原始数 据的一个副本,占据了大量的空间。实际上只需要使用 一部分缓冲区作为数据存储的中间部分,这需要借助队 列技术。
工具性能分析性能和内存
显示VI内存分配情况的工具
• 帮助分析程序中各个数据变量的内存拷贝情况
– 目标:消除黑点
工具性能分析显示缓存区分配
了解程序内存的使用
演示:监测内存使用
优化 LabVIEW程序内存管理
• 适时选择动态调用子VI • 避免强制类型转换 • 把复杂VI分解成多个子VI • 采用多面板程序 • 没必要时不要设置VI的重入特性 • 合理分配数组内存 • 灵活使用LabVIEW自带的VI • 使用元素同址操作结构In Place Element Structure
3、Deadline:用于指定完成一个循环的时间限定,如未在 指定的时间内完成,则左端数据节点Finished Late?[i-1]返 回真。默认值-1表示Deadline由Period决定。
4、如何处理某次循环使用的时间大于设定的周期? 是否丢弃丢失的了的循环?是否保持原始相位?
定时循环
定时循环
数组方式DEMO
队列函数方式DEMO
队列函数与数组的不同
1、消息传递方式不同 移位寄存器 & FIFO
2、释放消息队列的方式不同
用户界面事件模式
“我需要轮询用户的操作,但是这样会降低我程 序的运行速度,并且有时我还检测不到……”
LabVIEW中基于事件驱动的编程
LabVIEW事件示例 • 按下鼠标 • 键盘按键 • 前面板的用户交互
– 数据流 – 事件驱动 – 状态机结构 – 生产者/消费者
• 而功能型全局变量(functional global variable) 是为了避免竞争机制而实现的一种非重入型 子vi
定时结构
• 精确的定时 while 循环 • 精确的定时顺序结构 • 多个时钟频率的定时 • 反馈, 动态定时特性 • 多优先级设置 • examples\general\timedloop.llb
初始化时不 再需要用户 自定义事件
其他模式
“我希望同一时刻能够处理多个消息事件,而不 是下一个消息代码必须等待上一次响应完成后才 能执行”
“我不希望消息排队,等待很烦的,有时采集数据和 记录数据应该同时进行的”。
主从线程模式
通常应用于具有多个 同时发生的并且拥有 不同运行速率的线程 的程序中。比如采集 电压同时写入磁盘, 采集速率1KHz,记录 则每5秒一次。
答:“采用VI属性和方法接口,足以使你控制后台运行的VI”
例子:一个网络服务监听程序,程序只需要接收与客户端Sockets 的连接,实现三次握手,连接完成后将引用交给前端应用程序处理, 同时继续监听。
后台服务模式
后台服务模式
应用程序启动模式
“我想设计一个启动画面,同时显示应用程序加载的进度,加载 完毕后退出启动画面,运行主程序”
定时顺序结构
类似添加内置定时功能的顺序结构
定时循环
1、优先级:相对同一个程序框图中的多个定时循环 而言,优先级数大的循环优先执行。每一个定时循 环都有自己的线程,这里的优先级即线程优先级。
2、循环名称,对于可重入子VI中包含定时循环,且 该子VI的多个实例出现在同一个程序框图中,可以将 循环名称作为子VI的输入端子。
1、解决顺序型状态机不便阅读和修 改的问题,采用枚举型常量。
2、采用自定义型控件,方便修改。
over
消息队列模式
“我需要执行一系列的事件步骤,但是步骤顺序可通过 编程决定的。”
步骤是由用户界面事件决定的,如某个应用程序共要处 理4个状态,分别是A,B,C和D,前面板有3个按钮分别 控制3种运行时的状态序列ABCD、DCAB和BDCA。
基本工具
• 循环结构 • 移位寄存器 • 分支结构 • 枚举型常量 • 事件结构
状态机模式
“我需要执行一系列的事件步骤,但是步骤顺序 可通过编程决定的。”
自动贩卖机模型
Initialize
No input
Change Requeste
d
Change
Quarter Deposited
Wait
Nickel Deposited Dime Deposited
工作流程
Case结构对每一状态都配备 一个分支
移位寄存器用于传递状态
初始状态
枚举常量
切换代码根据执行步骤中的结果来 决定下一状态
FIRST STATE
执行步骤
切换代码
下一状态
枚举常量
枚举类型是一种允许程序员自定义 元素的数据类型,它可以显示数值对应 的具体含义,帮助程序员理解程序中使 用的变量值。
采用多面板程序
• 通过多面板程序实现只有在必要时才显示某些 窗口,因为界面显示是最费内存的,因此这样 可以极大降低内存的消耗。
没必要时不要设置VI的重入特性
• 重入型vi每次运行时都会对自己使用的数 据生成一个副本,这增加了内存开销
合理分配数组内存
• 过多进行内存重新分配占用很大开销 • 慎用可能导致内存重新分配的相关函数
• 变量 • 通知器 • 队列 • 信号量 • 集合
队列
在队列中添加元素
选择队列中元素的数据类型 Reference to existing queue in memory
从队列中释放元素
出列操作需要等待数据进入或者超时情况
生产者 / 消费者循环
后台服务模式
问:“我需要程序在后台运行,不要前面板,不要交互”
演示:定时循环
演示:定时循环
可具体手动设置定时循环运行的核
设置定时循环运 行的指定核
可具体手动设置定时循环运行的核
定时顺序结构Timed Sequence 含帧的定式循环Timed Loop with Frames
为什么要优化LabVIEW程序内存管理
• LabVIEW的自动管理内存特性
• 具有灵活的配置功能 • 被广泛使用
使用设计模式的益处
简化整个开发过程
– 更容易理解程序代码 – 代码可重用
可靠性
– 被使用多年,被证明其“可用并可靠” – 大量技术资源与例程
使用设计模式注意事项
1、不是一成不变的定律,既要知道有哪 些设计模式,还要知道每种模式解决实 际应用中的哪些问题,是如何解决的, 效果如何?
Quarter
Total < 50
Total >= 50
Total < 50
Total < 50
Dime
Total >= 50
Nickel
Total >= 50
Total > 50
Vend
Exit
Total = 50
基本三要素:
状态、事件、动作
背景
静态顺序结构
动态结构:允许不同的状态,按通过编程决定的顺序进 行执行
– 方便用户开发,满足一般应用需求
• LabVIEW应用程序趋向大型化,复杂化
– 项目规模大,需求复杂 – 数据处理量大,性能要求高
• 好的编程风格帮助LabVIEW优化内存管理
– 可以显著提高程序运行效率 – 需要了解LabVIEW的内存分配机制
监测VI内存占用和运行时间的工具
• 帮助定位和分析程序中的瓶颈部分
数据流入
存储单元
数据流出
生产者/消费者具体做法 最简单模式
在LabVIEW下实现生产者/消费者
• 无数据相关的多个循环 • 主 / 从关系 • 在循环间实现通讯与同步
工作流程
• 主循环负责通知各个从循环 是否执行
• 允许循环间异步执行 • 数据的非相关性实现多线程 • 程序过程分解
实现循环间的数据通讯
LabVIEW 事件结构
• 什么是事件结构?
– 带有多个子框图的结构节点, 就像条件结构
• 事件结构是如何工作的?
– 当面板上事件发生时才被唤醒 – 自动执行相应事件框图内的事件代码 – 当处理完成相应事件后便结束,并不一直循环等
待
为什么要使用事件结构 ?
• 用更简单的事件处理替代原来的查询循环 • 最小化 CPU 的使用 • 不会遗漏用户界面交互事件 • 可检测更多的交互事件 • 编程生成您自己的事件
– 创建数组 – 连接字符串
演示:编程方法影响程序性能
总在开辟新内存,必定时间长
演示:编程方法影响程序性能
循环次数并非事先指定,因此每次循环也会开 辟新的内存,但节省了Build Array函数的时间。
演示:编程方法影响程序性能
循环无需开辟新的内存,时间会明显减少。
2、文本式编程语言中广泛使用的设计模 式在图形化数据流编程中的应用问题。
注意!
有些时候你没有必要选用最 复杂的设计模式
不要忘记最常见的设计模式 ——数据流!
LabVIEW设计模式
通用型:状态机模式、
消息队列模式、 用户界面事件模式
专用型:主从线程模式、
生产/消费模式、 后台服务模式、 应用程序启动模式、 代理模式
引入消息队列模式,通过建立队列缓冲区来解决这个问 题,这种模式也称为“队列型状态机模式”。
消息处理过程
建立消息队列
消息源
加入消息
探测消息
No
EXIT?
Yes 销毁消息队列
删除消息
接收消息 执行代码
队列建立方式 队列函数和数组
队列函数
最常用的 4个函数
数组 1、数组函数 2、配合移位寄存器 3、无需手动销毁队列空间
1、获取要处理事件对象的VI服务器引用; 2、将VI服务器引用连接至“注册事件”函数; 3、将事件结构放在While循环中,等待处理 对象事件直到终止条件出现;
4、通过取消注册时间函数停止事件发生。
动态事件注册demo
最值器
用户界面事件demo 一个动态+5个静态
状态机——用户界面事件混合demo