|
这个Demo整合了所有适配汇川 H5U 的核心要点,从环境搭建、代码编写、PLC 配置到联调验证,全程零基础友好,代码可直接复制运行,解决了汇川 CDAB 字节序、地址映射、通信超时等核心痛点,是工控上位机开发的实战指南。 一、核心适配要点(汇川 H5U vs 通用 Modbus) 核心项 | 汇川 H5U 规则 | 实操注意 | Modbus 服务器 | 默认启用(端口 502、从站地址 1) | 无需手动配置,PLC 需切 RUN 模式 | 地址映射 | Dn = Modbus 40001 + n(如 D100=40101) | 避免按西门子习惯误写为 40001 | 浮点数字节序 | CDAB(低 16 位 CD 在前,高 16 位 AB 在后) | 解析 / 写入需按此顺序拼接字节 | 通信超时 | 建议设置 1000ms | 避免过短超时或过长阻塞 UI |
--- 二、开发环境准备 1. 软件工具 • 开发工具:Visual Studio 2022/2026(.NET Framework 4.8); • PLC 编程软件:汇川 AutoShop V4.11+; • 类库:NModbus4(4.0.0 版本,工控最稳定); • 辅助工具:Wireshark(抓包验证,可选)。 2. NuGet 安装 NModbus4 打开 VS→右键项目→管理 NuGet 程序包→搜索 “NModbus4”→选择 4.0.0 版本安装: Install-Package NModbus4 -Version 4.0.0 三、完整项目实现(代码 + 界面) 1. 界面设计(工控极简版) 控件布局 2. 核心业务代码(适配汇川 CDAB 字节序) 打开FrmHcModbus.cs,粘贴以下代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 using System;using System.Net.Sockets;using System.Windows.Forms;using Modbus.Device;namespace ModbusTcpClientDemo{ public partial class FrmHcModbus : Form { // Modbus核心对象 private TcpClient _tcpClient; private IModbusIpMaster _modbusMaster; // 连接状态标记 private bool _isConnected = false; // 汇川H5U默认从站地址 private byte _slaveAddress = 1; public FrmHcModbus() { InitializeComponent(); // 窗体关闭时断开连接 this.FormClosing += (s, e) => DisconnectPlc(); } #region 1. 连接/断开汇川H5U PLC private void btnConnect_Click(object sender, EventArgs e) { if (!_isConnected) { try { _tcpClient = new TcpClient(); // 1000ms连接超时(工控场景最优) var connectTask = _tcpClient.ConnectAsync(txtPlcIp.Text, (int)nudPort.Value); if (!connectTask.Wait(1000)) { throw new TimeoutException("连接超时,请检查IP/网段或PLC状态"); } // 创建Modbus IP主站 _modbusMaster = ModbusIpMaster.CreateIp(_tcpClient); _modbusMaster.Transport.ReadTimeout = 1000; _modbusMaster.Transport.WriteTimeout = 1000; _isConnected = true; lblStatus.Text = $"已连接:{txtPlcIp.Text}:{nudPort.Value}"; lblStatus.ForeColor = System.Drawing.Color.Green; btnConnect.Text = "断开连接"; } catch (Exception ex) { lblStatus.Text = $"连接失败:{ex.Message}"; lblStatus.ForeColor = System.Drawing.Color.Red; DisconnectPlc(); } } else { DisconnectPlc(); lblStatus.Text = "已断开连接"; lblStatus.ForeColor = System.Drawing.Color.Gray; btnConnect.Text = "连接H5U PLC"; } } /// <summary> /// 断开PLC连接,释放资源 /// </summary> private void DisconnectPlc() { if (_isConnected) { _modbusMaster?.Dispose(); _tcpClient?.Close(); _tcpClient?.Dispose(); _isConnected = false; } } #endregion #region 2. 读取汇川H5U数据(支持16位整数+32位浮点数CDAB) private void btnRead_Click(object sender, EventArgs e) { if (!_isConnected) { MessageBox.Show("请先连接汇川H5U PLC!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } try { txtReadResult.Clear(); // 地址转换:Modbus 40101 → 汇川D100(40101-40001=100) ushort startAddr = (ushort)((int)nudStartAddr.Value - 40001); ushort readCount = (ushort)nudReadCount.Value; int hcDaddr = (int)nudStartAddr.Value - 40000; // 汇川D寄存器编号 // 读取保持寄存器(汇川D寄存器对应Modbus 4xxxx) ushort[] readValues = _modbusMaster.ReadHoldingRegisters( _slaveAddress, // 从站地址 startAddr, // 偏移地址 readCount // 读取数量 ); // 解析数据并显示 txtReadResult.AppendText($"===== 汇川H5U读取结果(CDAB字节序)=====\r\n"); txtReadResult.AppendText($"读取起始地址:Modbus {nudStartAddr.Value}(汇川D{hcDaddr})\r\n"); txtReadResult.AppendText($"读取数量:{readCount} 个寄存器\r\n"); txtReadResult.AppendText($"====================================\r\n"); for (int i = 0; i < readValues.Length; i++) { int currentDaddr = hcDaddr + i; // 显示16位整数 txtReadResult.AppendText($"汇川D{currentDaddr}:{readValues}(16位整数)\r\n"); // 解析32位浮点数(CDAB字节序,每2个寄存器解析1个) if (i + 1 < readValues.Length && i % 2 == 0) { byte[] bytes = new byte[4]; // 汇川CDAB字节序:Dn=CD(低16位),Dn+1=AB(高16位) bytes[0] = (byte)(readValues & 0xFF); // C bytes[1] = (byte)(readValues >> 8); // D bytes[2] = (byte)(readValues[i + 1] & 0xFF); // A bytes[3] = (byte)(readValues[i + 1] >> 8); // B float floatValue = BitConverter.ToSingle(bytes, 0); txtReadResult.AppendText($"汇川D{currentDaddr}-D{currentDaddr + 1}:{floatValue:F2}(32位浮点数)\r\n"); txtReadResult.AppendText($"------------------------------------\r\n"); i++; // 跳过已解析的寄存器 } } lblStatus.Text = "读取成功(CDAB字节序)"; } catch (Exception ex) { lblStatus.Text = $"读取失败:{ex.Message}"; txtReadResult.AppendText($"读取失败:{ex.Message}\r\n"); } } #endregion #region 3. 写入16位整数到汇川H5U private void btnWriteInt_Click(object sender, EventArgs e) { if (!_isConnected) { MessageBox.Show("请先连接汇川H5U PLC!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } try { // 校验输入 if (!ushort.TryParse(txtWriteIntValue.Text, out ushort writeValue)) { MessageBox.Show("请输入0-65535之间的整数!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // 地址转换 ushort startAddr = (ushort)((int)nudStartAddr.Value - 40001); int hcDaddr = (int)nudStartAddr.Value - 40000; // 写入单寄存器(06指令) _modbusMaster.WriteSingleRegister( _slaveAddress, startAddr, writeValue ); lblStatus.Text = "整数写入成功"; MessageBox.Show($"成功写入16位整数 {writeValue} 到汇川D{hcDaddr}!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { lblStatus.Text = $"整数写入失败:{ex.Message}"; MessageBox.Show($"写入失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } #endregion #region 4. 写入32位浮点数到汇川H5U(CDAB字节序) private void btnWriteFloat_Click(object sender, EventArgs e) { if (!_isConnected) { MessageBox.Show("请先连接汇川H5U PLC!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } try { // 校验输入 if (!float.TryParse(txtWriteFloatValue.Text, out float floatValue)) { MessageBox.Show("请输入有效的浮点数(如10.0、25.5)!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } // 地址转换 ushort startAddr = (ushort)((int)nudStartAddr.Value - 40001); int hcDaddr = (int)nudStartAddr.Value - 40000; // 浮点数转汇川CDAB字节序的2个寄存器 ushort[] regs = HcFloatToUshorts(floatValue); // 写入多寄存器(16指令,2个寄存器) _modbusMaster.WriteMultipleRegisters( _slaveAddress, startAddr, regs ); lblStatus.Text = "浮点数写入成功"; MessageBox.Show($"成功写入32位浮点数 {floatValue:F2} 到汇川D{hcDaddr}-D{hcDaddr + 1}!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { lblStatus.Text = $"浮点数写入失败:{ex.Message}"; MessageBox.Show($"写入失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } /// <summary> /// 32位浮点数转汇川H5U的2个16位寄存器(CDAB字节序) /// </summary> /// <param name="floatValue">待转换浮点数 /// <returns>寄存器数组:[低16位CD, 高16位AB]</returns> private ushort[] HcFloatToUshorts(float floatValue) { byte[] bytes = BitConverter.GetBytes(floatValue); ushort[] registers = new ushort[2]; // CDAB字节序:低16位=CD(bytes[0]+bytes[1]),高16位=AB(bytes[2]+bytes[3]) registers[0] = BitConverter.ToUInt16(new byte[] { bytes[0], bytes[1] }, 0); registers[1] = BitConverter.ToUInt16(new byte[] { bytes[2], bytes[3] }, 0); return registers; } #endregion }} 四、汇川 H5U PLC 侧配置(极简步骤) 1. 基础配置 1. 打开汇川 AutoShop,连接 H5U PLC; 2. 配置 PLC IP:双击 “系统参数→以太网→本地 IP”,设置为192.168.0.100(和上位机同网段); 3. 确认 Modbus TCP 服务器:“系统参数→以太网→Modbus TCP 服务器”,勾选 “启用”(默认已勾选),端口 502; 4. 下载参数到 PLC,切换到RUN模式(RUN 灯常亮)。 2. 测试数据准备 1. 打开 “监控表”,添加D100、D101; 2. 手动赋值:D100=123,D101=456(测试整数);或直接输入浮点数 10.0(AutoShop 自动拆分字节)。 --- 五、联调验证步骤(新手必看) 1. 连接测试 • 上位机输入 PLC IP192.168.0.100,(如果没有实体PLC,模拟话的可以输入127.0.0.1)点击 “连接 H5U PLC”; • 状态栏显示 “已连接:192.168.0.100:502”(127.0.0.1)(绿色),说明连接成功。 2. 读取测试 • 起始地址40101(D100),读取数量2; • 点击 “读取数据”,界面显示:plaintext===== 汇川H5U读取结果(CDAB字节序)=====读取起始地址:Modbus 40101(汇川D100)读取数量:2 个寄存器====================================汇川D100:102(16位整数)汇川D100-D101:100.50(32位浮点数,若D100=123、D101=456)------------------------------------ (若 PLC 中输入浮点数 10.0,此处浮点数显示 10.00) 3. 写入测试 • 写入整数:输入200,点击 “写入整数”,PLC 监控表 D100 变为 200; • 写入浮点数:输入25.5,点击 “写入浮点数”,PLC 监控表 D100-D101 显示 25.5。 --- 六、汇川 H5U 专属避坑手册 1. 地址映射错误(最高发) • 错误:Modbus 40001 对应汇川 D100; • 正确:Modbus 地址 = 40001 + D 寄存器编号 - 1(如 D100=40101)。 2. 字节序解析乱码 • 错误:按西门子 ABCD 顺序拼接字节; • 正确:汇川 CDAB 顺序(低 16 位 CD 在前,高 16 位 AB 在后)。 3. PLC 未切 RUN 模式 • 汇川 H5U 在 STOP 模式下不响应 Modbus 请求,必报 “超时”; • 验证:PLC 面板 RUN 灯常亮再调试。 4. 网段 / IP 冲突 • 上位机和 PLC 必须同网段(如 192.168.0.X); • 测试:CMD 输入ping 192.168.0.100,能通再连接。 5. 浮点数写入寄存器数量 • 写入浮点数需占用 2 个寄存器,读取数量必须设为偶数; • 若设为奇数,最后 1 个寄存器无法解析为浮点数。 --- 七、总结 1. 汇川 H5U 适配核心是地址映射(Dn=40001+n-1)和CDAB 字节序(低 16 位在前); 2. 代码复用通用 Modbus TCP 逻辑,仅需调整浮点数解析 / 写入的字节拼接顺序; 3. 联调关键步骤:先验证整数读写,再测试浮点数,逐步排查地址 / 字节序问题; 4. 避坑重点:PLC RUN 模式、网段匹配、地址换算,解决 80% 的通信问题。 公众号回复「H5U」,即可获取:完整可运行代码。 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |