『7x24小时有问必答』
  
这个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 版本安装:

1

Install-Package NModbus4 -Version 4.0.0

三、完整项目实现(代码 + 界面)

1. 界面设计(工控极简版)

控件布局

1.png

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. 打开 “监控表”,添加D100D101
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.png

2. 读取测试

3.jpeg
• 起始地址40101(D100),读取数量2
• 点击 “读取数据”,界面显示:

plaintext

1
2
3
4
5
6
7

===== 汇川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」,即可获取:完整可运行代码。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

上一主题上一主题         下一主题下一主题
QQ手机版小黑屋粤ICP备17165530号

关于我们·投诉举报· 用户帮助· 联系我们 · 本站服务 · 版权声明· 隐私政策 · 投搞指南

法律保护:PLC技术网,plcjs.com,plcjs.net等字样
Copyright 2010-2030. All rights reserved. 


微信公众号二维码 抖音二维码 百家号二维码 今日头条二维码哔哩哔哩二维码