1. 项目背景与核心需求
在工业自动化领域,PLC与智能电表的数据交互是能源管理系统的基础环节。这次要分享的是基于西门子S7-1200 PLC通过485自由口协议与DLT645-2007规约电表通讯的完整实现方案。这个项目源于某工厂电能监测系统的实际需求——需要实时采集20台电表的有功功率、电压电流等48项参数,数据刷新周期要求≤5秒。
传统Modbus RTU方案虽然常见,但国内90%以上的智能电表采用DLT645-2007行业标准协议。该协议采用变长帧结构,包含起始符、地址域、控制码、数据长度、数据域、校验和等复杂字段,相比Modbus的固定格式实现难度更高。特别在以下三个场景中尤为关键:
- 需解析电表冻结数据时(如月冻结、日冻结)
- 读取需进行数据项标识编码的参数时(如0x00 0x02代表A相电压)
- 处理电表主动上报的异常事件帧时
2. 硬件配置与接线规范
2.1 硬件选型要点
- PLC型号:S7-1214C DC/DC/DC(6ES7 214-1AG40-0XB0)
- 关键参数:支持RS485通讯板(6ES7 241-1CH32-0XB0),波特率可调范围1200-115200bps
- 电表型号:社为表计DDSU666(兼容DLT645-2007)
- 注意:不同厂家对协议扩展不一致,需确认"数据标识编码表"
- 通讯线材:屏蔽双绞线(AWG22)带铠装层,阻抗120Ω
2.2 接线实操细节
plaintext复制PLC RS485-A(引脚3) —— 电表端子A(端子8)
PLC RS485-B(引脚8) —— 电表端子B(端子9)
PLC CM(引脚5) —— 电表接地端子(端子10)
重要提示:必须在PLC侧加装120Ω终端电阻(通过硬件组态使能),总线两端电表处并联相同阻值电阻。实测显示,未加终端电阻时300米以上通讯误码率升高40%。
3. 博图环境配置关键步骤
3.1 硬件组态
- 在设备视图中添加CM1241 RS485模块
- 设置工作模式为"半双工(RS485)"
- 波特率设为9600(与电表参数一致)
- 校验方式选择"偶校验"(DLT645标准要求)
3.2 自由口协议配置
使用"Send_CFG"指令配置通讯参数:
STL复制"Send_DB".STARTUP := TRUE;
"Send_DB".BAUD := 9600;
"Send_DB".PARITY := 2; //偶校验
"Send_DB".FLOW_CTRL := 0; //无流控
"Send_DB".RESP_TO := 500; //响应超时500ms
4. DLT645协议帧解析与实现
4.1 典型请求帧结构
以读取A相电压(数据标识0x00 0x02)为例:
python复制# 原始帧(十六进制)
68 AA AA AA AA AA AA 68 11 04 33 33 34 33 CS 16
- 地址域AA...AA:6字节电表地址(需BCD码转换)
- 控制码0x11:读数据
- 数据标识0x00 0x02:A相电压
- CS校验和:从起始符到校验前所有字节累加和
4.2 PLC程序实现
SCL复制// 构建请求帧
#SendBuffer[0] := 16#68; //起始符
FOR #i := 1 TO 6 DO
#SendBuffer[#i] := BCD_TO_INT(#MeterAddress[#i]); //地址域转换
END_FOR;
#SendBuffer[7] := 16#68; //结束符
#SendBuffer[8] := 16#11; //控制码
#SendBuffer[9] := 16#04; //数据长度
#SendBuffer[10] := 16#33; //数据标识1
#SendBuffer[11] := 16#33; //数据标识2
#SendBuffer[12] := 16#34;
#SendBuffer[13] := 16#33;
#CheckSum := 0;
FOR #j := 0 TO 13 DO
#CheckSum := #CheckSum + #SendBuffer[#j];
END_FOR;
#SendBuffer[14] := #CheckSum MOD 256; //校验和
#SendBuffer[15] := 16#16; //结束符
5. 数据解析与处理技巧
5.1 响应帧解码
典型响应帧示例:
python复制68 AA AA AA AA AA AA 68 91 08 33 33 34 33 02 22 6F 35 CS 16
- 控制码0x91:读数据应答
- 数据域02 22 6F 35:需进行"33H反转"处理
- 实际值 = (0x35-0x33) (0x6F-0x33) (0x22-0x33) (0x02-0x33)
- 最终值:02 3C EF CF → 转换为十进制电压值
5.2 数据转换FB块
SCL复制FUNCTION "DLT645_Decode" : REAL
VAR_INPUT
IN : ARRAY[0..3] OF BYTE; //原始4字节数据域
END_VAR
VAR_TEMP
tempValue : DWORD;
END_VAR
BEGIN
// 33H反转处理
FOR #i := 0 TO 3 DO
#IN[#i] := #IN[#i] - 16#33;
END_FOR;
// 组合为32位整数
tempValue := SHL(IN[3], 24) OR SHL(IN[2], 16) OR SHL(IN[1], 8) OR IN[0];
// 转换为浮点数(假设小数位2位)
"DLT645_Decode" := DINT_TO_REAL(tempValue) / 100.0;
END_FUNCTION
6. 异常处理与优化策略
6.1 典型故障排查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 通讯超时 | 终端电阻未配置 | 在总线两端并联120Ω电阻 |
| 校验错误 | 电表地址BCD码转换错误 | 检查地址域字节处理逻辑 |
| 数据解析异常 | 未进行33H反转处理 | 在解码前对数据域每个字节减0x33 |
| 间歇性通讯中断 | 波特率不匹配 | 用示波器测量实际波特率 |
6.2 性能优化建议
- 轮询策略:采用"分组轮询+变化触发"机制,将20块电表分为4组,基础参数每5秒读取一次,重要参数(如功率)1秒读取
- 数据缓存:在DB块中建立镜像数据区,HMI直接读取镜像值避免实时通讯延迟
- 错误重试:实现三级重试机制(立即重试→延时重试→地址确认)
7. 工程文档规范建议
7.1 注释标准示例
SCL复制// 功能:DLT645协议帧构建
// 作者:张三
// 日期:2023-08-20
// 修改记录:
// V1.0 初始版本
// V1.1 增加地址域BCD码转换
FUNCTION_BLOCK "FB_DLT645_Request"
7.2 配套文档目录
- 《电表地址分配表.xlsx》
- 包含所有电表的物理地址、逻辑编号、安装位置
- 《数据标识编码对照表.docx》
- 记录0x0001-0xFFFF对应的参数含义及单位
- 《通讯异常处理手册.pdf》
- 典型故障处理流程图及示波器波形图
在实际项目中,我们发现电表时钟同步是个易忽略点。建议每月通过广播校时命令(控制码0x08)对所有电表进行时间同步,避免冻结数据时间戳错乱。某次现场故障正是因为电表时钟电池耗尽导致日冻结数据全部错位,后来在程序中增加了时钟偏差报警功能才彻底解决。