主题
模拟量与工程量例程 5:状态字拆分与合并(取位 / 合并位)
这一页只讲这一个例程。母页 b-03-analog-scaling 里留着例程 1,其余例程各自一页、在那一页的目录里点。
场景:第三方设备给回来一个"状态字"(16 位,每位一个状态),要拆成开关量分别判断;反过来把本机状态拼成一个字,一次写寄存器、一次上云。
软元件
| 软元件 | 作用 |
|---|---|
D500 | 第三方状态字(DTU 采集回来) |
M200 / M201 | 拆出的状态(1#运行 / 1#故障) |
D510 | 拼好的本机状态字 |
块图(照着拖即可)
对应的 ddc.json(点「生成 JSON」得到的就是它;也可存成 .ddc.json 导入)
json
{
"version": 1,
"name": "状态字拆分合并",
"scan_ms": 200,
"lines": [
{
"op": "assign",
"target": {"op":"ref","device":"M","addr":200},
"expr": {"op":"bitget","bit":0,"args":[{"op":"ref","device":"D","addr":500}]}
},
{
"op": "assign",
"target": {"op":"ref","device":"M","addr":201},
"expr": {"op":"bitget","bit":1,"args":[{"op":"ref","device":"D","addr":500}]}
},
{
"op": "assign",
"target": {"op":"ref","device":"Y","addr":20},
"expr": {
"op": "and",
"args": [
{"op":"ref","device":"M","addr":200},
{"op":"not","args":[{"op":"ref","device":"M","addr":201}]}
]
}
},
{
"op": "assign",
"target": {"op":"ref","device":"D","addr":510},
"expr": {
"op": "bitmerge",
"args": [
{"op":"ref","device":"M","addr":300},
{"op":"ref","device":"M","addr":301},
{"op":"ref","device":"M","addr":302},
{"op":"ref","device":"M","addr":303},
{"op":"const","value":0},
{"op":"const","value":0},
{"op":"const","value":0},
{"op":"const","value":0},
{"op":"const","value":0},
{"op":"const","value":0},
{"op":"const","value":0},
{"op":"const","value":0},
{"op":"const","value":0},
{"op":"const","value":0},
{"op":"const","value":0},
{"op":"const","value":0}
]
}
}
]
}要点
- 取位:从整数里取 BIT0~BIT15 的某一位,也能取整数部分。
- 合并位:把最多 16 路 0/1 合并成一个整数(每路一个位);未接的位生成器补常量 0。
- 位号从 BIT0 开始(最低位),对接第三方协议时先确认对方的位定义。
验证:D500 写 1 → M200 = 1;写 2 → M201 = 1;写 3 → 两个都为 1。M300~M303 分别置位 → D510 = 1 / 2 / 4 / 8 的累加值。
注意事项
- 位号数错一位:所有状态都错位,且看起来"像是对的",很难查。对接时先用一个已知值验证一遍。
- 合并位时不接的路按 0 处理,云端按位解析时会少状态。
- 把拼好的 D510 又当输入拆回去:源和目的分开两个寄存器,避免自己覆盖自己。