跳到主要内容

DL/T 645

Zeus 的 DL/T 645 模块面向电能表和能耗采集设备,支持 DL/T 645-2007 常用数据项读取与写入。协议层已经处理表地址反序、帧前导 0xFE、双 0x68 帧头、0x33 数据偏移、校验和、异常码,以及低字节在前的 BCD 数据解码。

无硬件先跑通

const string meterAddress = "000000000001";

var memory = new Dlt645SlaveMemory();
memory.SetBcd(0x00000000, 1234.56, byteLength: 4, scale: 0.01);
memory.SetBcd(0x02010100, 220.5, byteLength: 2, scale: 0.1);

await using var app = ZeusHost.Create(builder =>
{
builder.AddVirtualChannel("meter-link", new Dlt645SlaveResponder(meterAddress, memory));
builder.AddDlt645(
"meter",
"meter-link",
new Dlt645Options { MeterAddress = meterAddress, WakeUpPreambleCount = 0 },
points: map => map
.Bcd("energy", 0x00000000, dataLength: 4, scale: 0.01)
.Bcd("voltageA", 0x02010100, dataLength: 2, scale: 0.1));
});

await app.StartAsync();
组件含义
Dlt645SlaveMemory虚拟表计的数据项映像,键是四字节 DI
Dlt645SlaveResponder(address, memory)模拟一个指定表地址的 DL/T 645 表计
AddDlt645("meter", "meter-link", options)在已有通道上登记 DL/T 645 设备
.Bcd("energy", 0x00000000, 4, 0.01)把组合有功总电能数据项映射成点表点

可运行示例:samples/Zeus.Samples.Console.Dlt645

接真实表计

DL/T 645 通常走 RS-485 串口。通道只负责收发字节,表地址和协议帧由 Dlt645Device 处理:

await using var app = ZeusHost.Create(builder =>
{
builder.AddSerialPort("meter-link", "COM3", 2400);
builder.AddDlt645(
"meter",
"meter-link",
new Dlt645Options
{
MeterAddress = "000000000001",
WakeUpPreambleCount = 4
},
points: map => map.TotalActiveEnergy("energy"));
});

一些 TCP/串口服务器会透传 DL/T 645 帧,这时把通道换成 TCP 即可:

builder.AddTcpClient("meter-link", "192.168.1.50", 5000);
builder.AddDlt645("meter", "meter-link", new Dlt645Options { MeterAddress = "000000000001" });

直接读写数据项

var meter = app.Devices.Get<Dlt645Device>("meter");

var energy = await meter.ReadBcdAsync(0x00000000, byteLength: 4, scale: 0.01);
var voltageA = await meter.ReadBcdAsync(0x02010100, byteLength: 2, scale: 0.1);

var raw = await meter.ReadDataAsync(0x04000401);
await meter.WriteBcdAsync(0x04000101, 88.8, byteLength: 2, scale: 0.1);

ReadDataAsync 返回的数据不含四字节 DI,也不含协议里的 0x33 偏移。BCD 数值按低字节在前解析,例如 4 字节、scale: 0.01 常用于 XXXXXX.XX 格式电量。

点表采集

builder.AddAcquisition(TimeSpan.FromSeconds(1));
builder.AddDlt645("meter", "meter-link", new Dlt645Options { MeterAddress = "000000000001" }, points: map => map
.Bcd("energy", 0x00000000, dataLength: 4, scale: 0.01, alarmLimits: new PointAlarmLimits(high: 10000))
.Bcd("voltageA", 0x02010100, dataLength: 2, scale: 0.1)
.RawBytes("status", 0x04000401, dataLength: 1));
点类型点表值说明
Bcddoublescale 换算后的工程值,支持报警限和写回
RawBytesbyte[]保留原始数据字节,适合状态字或厂家扩展数据项

常用快捷方法:

map.TotalActiveEnergy("energy"); // DI 00000000, 4 字节, 0.01 kWh
map.VoltageA("voltageA"); // DI 02010100, 2 字节, 0.1 V
map.CurrentA("currentA"); // DI 02020100, 3 字节, 0.001 A

JSON 配置

{
"channels": [
{
"name": "meter-link",
"type": "serial",
"portName": "COM3",
"baudRate": 2400
}
],
"devices": [
{
"name": "meter",
"channel": "meter-link",
"type": "dlt645",
"meterAddress": "000000000001",
"wakeUpPreambleCount": 4,
"points": [
{ "name": "energy", "address": "0x00000000", "dataType": "bcd", "dataLength": 4, "scale": 0.01 },
{ "name": "voltageA", "address": "0x02010100", "dataType": "bcd", "dataLength": 2, "scale": 0.1 },
{ "name": "status", "address": "0x04000401", "dataType": "raw", "dataLength": 1 }
]
}
]
}

无硬件联调时,把通道换成:

{
"name": "meter-link",
"type": "virtual",
"responder": "dlt645",
"meterAddress": "000000000001"
}

可直接复制的配置样例位于 samples/Zeus.Samples.Console.Config/zeus-dlt645.json

常见数据项

数据项常见含义建议声明
0x00000000当前组合有功总电能dataLength: 4, scale: 0.01
0x02010100A 相电压dataLength: 2, scale: 0.1
0x02020100A 相电流dataLength: 3, scale: 0.001

不同厂家会扩展数据项,最终以表计通信规约或点表手册为准。

排错

现象最可能原因处理
一直超时表地址、波特率、校验位或前导 0xFE 数量不匹配先用虚拟表计跑通,再对照现场参数
校验和错误串口参数不一致或线路干扰打开通信追踪,确认原始帧和校验范围
异常码 0x02表计没有该数据项核对数据项 DI 和表计型号
数值差 10/100 倍scale 不匹配按手册调整 scaledataLength