循环状态支持(Loop Support)
概述
CSM Loop Support 是一个内置 Addon,为 CSM 状态机提供标准化的循环实现机制。它让你可以在状态机中实现连续循环操作,同时不阻塞状态机的运行、仍然能够响应外部消息。
功能说明
为什么需要 Loop Support?
在 CSM 状态机中实现循环有两种直观的方式,但都存在问题:
| 方案 | 做法 | 问题 |
|---|---|---|
| 在 Case 中嵌套 While 循环 | 在状态分支里直接写 While Loop | 状态机卡死在此状态,无法响应外部消息 |
| 用状态链实现循环 | 在最后一个状态中继续插入下一轮的状态 | 响应外部消息不及时,逻辑不直观 |
Loop Support 通过特殊标记(-><loop> 和 -><end>)对状态队列进行分析和调度,实现了以下优势:
- ✅ 循环运行时仍可响应外部消息,不阻塞状态机
- ✅ 同步消息(高优先级)立即打断循环执行
- ✅ 异步消息插队到
-><end>之后,在下一轮循环前处理 - ✅ 无需手动嵌套 While 循环,逻辑清晰直观
应用范围限制
CSM 的协作者模式(Worker)和责任链模式(Chain)由多个节点组成,发送的消息无法明确指定某个节点执行,因此不建议在这两种模式中使用 Loop Support。
API 函数列表
Loop Support Addon 提供以下 4 个主要 API(均在 Addons - Loop Support 函数选板中):
| 函数名 | 作用 | 使用时机 |
|---|---|---|
CSMLS - Define Loop State(s).vi | 定义循环,用 -><loop> 标记循环状态 | 启动循环时(如 API: Start DAQ) |
CSMLS - Append Continuous State.vi | 添加下一轮循环状态,维持循环运行 | 循环检查状态中(如 DAQ: Continue Check) |
CSMLS - Remove Loop Tag to Break.vi | 移除 -><loop> 标记,完成当前轮后退出 | 需要完成当前轮操作后再退出循环 |
CSMLS - Remove Loop Tag and previous State(s) to Break.vi | 移除标记及之前所有状态,立即退出 | 需要跳过当前轮未完成的操作立即退出 |
还有一个内部 VI:
CSMLS - Add Exit State(s) with Loop Check.vi,该 VI 已集成到Parse State Queue++.vi的Macro: Exit处理中,已从函数选板移除,无需手动调用。
调用逻辑说明
状态队列标记机制
Loop Support 通过在状态队列中插入特殊标记来管理循环:
状态队列示意:
DAQ: Initialize
DAQ: Start
DAQ: Acquire
DAQ: Continue Check -><loop> ← 循环检查点标记
DAQ: Stop
DAQ: Close -><end> ← 循环结束标记(自动添加)
整体调用流程
flowchart TD
A["外部消息\nAPI: Start DAQ"] --> B["CSMLS - Define Loop State(s).vi\n定义循环状态队列,打上 -><loop> 标记"]
B --> C["DAQ: Initialize\nDAQ: Start\nDAQ: Acquire\nDAQ: Continue Check -><loop>\nDAQ: Stop\nDAQ: Close -><end>"]
C --> D{"执行到\nContinue Check?"}
D -- 继续循环 --> E["CSMLS - Append Continuous State.vi\n将下一轮 Acquire 插到队列前端"]
E --> F{"队列中有\n外部消息?"}
F -- 无外部消息 --> G["Wait 延迟\n回到 DAQ: Acquire"]
F -- 有异步消息 --> H["先处理异步消息\n再回到循环"]
D -- 停止循环 --> I{"停止方式?"}
I -- 完成当前轮后退出 --> J["CSMLS - Remove Loop Tag to Break.vi\n移除 -><loop>,执行完剩余状态后退出"]
I -- 跳过当前轮立即退出 --> K["CSMLS - Remove Loop Tag and\nprevious State(s) to Break.vi\n移除 -><loop> 及之前状态,立即退出"]
J --> L["DAQ: Stop → DAQ: Close\n正常收尾"]
K --> L
L --> M["循环结束"]
N["外部同步消息\n(高优先级)"] -- "立即打断循环" --> D
两种停止方式对比
假设当前队列中还有以下状态时触发停止:
DAQ: Acquire
DAQ: Continue Check -><loop>
DAQ: Stop
DAQ: Close
| 停止方式 | 效果 | 适用场景 |
|---|---|---|
Remove Loop Tag to Break | 移除 -><loop> 行,依然执行 DAQ: Acquire → Stop → Close | 完成当前轮操作后退出 |
Remove Loop Tag and previous State(s) to Break | 移除 DAQ: Acquire 和 -><loop> 行,直接执行 DAQ: Stop → Close | 跳过当前轮,立即进入收尾 |
Add to Front? 参数说明
CSMLS - Define Loop State(s).vi的 Add to Front? 参数通常应保持 FALSE。原因:循环状态一旦开始,就不会立即结束。如果设为 TRUE(插入队列前端),当前状态如果是被同步消息调用的,就不会立即返回,导致同步调用超时。
只有当你希望等待循环全部完成后再返回时,才设为 TRUE。
典型应用场景
连续数据采集(DAQ)
这是 Loop Support 最典型的应用场景。
需求:持续采集数据,同时允许外部随时停止采集。
API: Start DAQ >> {
CSMLS - Define Loop State(s).vi
Loop States:
"DAQ: Initialize
DAQ: Start
DAQ: Acquire
DAQ: Continue Check -><loop>
DAQ: Stop
DAQ: Close -><end>"
// 注意 Add to Front? = FALSE,立即返回,后台开始循环
}
DAQ: Acquire >> {
// 执行一次采集
Acquire Data → 更新波形图
}
DAQ: Continue Check >> {
// 循环检查点:有 -><loop> 标记
CSMLS - Append Continuous State.vi
Continuous State: "DAQ: Acquire"
Wait 100ms // 控制采集速率
}
API: Stop DAQ >> {
// 外部停止命令
CSMLS - Remove Loop Tag to Break.vi
// 完成当前采集后,自动执行 DAQ: Stop → DAQ: Close
}
Error: High Priority >> {
// 高优先级错误,立即中止
CSMLS - Remove Loop Tag and previous State(s) to Break.vi
// 跳过剩余采集,直接 DAQ: Stop → DAQ: Close
}
参考示例:Addons - Loop Support\CSMLS - Continuous Loop in CSM Example.vi
注意事项
-
必须添加延迟:在循环检查状态中,应使用
Wait函数控制循环速率,避免 CPU 占用过高。 -
退出时自动清理:
Macro: Exit消息处理时,Parse State Queue++.vi已自动调用CSMLS - Add Exit State(s) with Loop Check.vi,会检查并清理-><loop>标记,无需手动处理。 -
不适用 Worker/Chain 模式:参见应用范围限制。
-
同步消息优先:在循环运行时发送的同步消息会立即打断循环执行,执行完毕后循环恢复。
参考资料
- API 参考:内置插件 → CSM周期状态支持
- 官方示例:
Addons - Loop Support\CSMLS - Continuous Loop in CSM Example.vi