在上一个文章中我们讲过 三菱FX5U PLC支持多种通信协议,根据项目需求可选择不同的通讯方式,以下是几种主流通讯方式对比。
| MX Component库 (ActUtlType) | MC协议 (SLMP/3E帧) - 原生TCP/IP | 第三方开源库 | Modbus TCP桥接 |
| 使用三菱提供的ActiveX控件ActUtlTypeLib | 基于三菱私有协议MC协议,通过Socket发送特定格式指令 | 使用开源第三方库,封装了协议细节 | 将FX5U配置为Modbus TCP主站/从站 |
| 官方支持,稳定性较高,编程相对简单,但可能需要购买授权,依赖特定组件 | 灵活性强,无需额外授权,性能较好,但需手动组帧和解帧,处理错误码,开发复杂度稍高 | 开源免费,API友好,支持多种PLC品牌 | 通用标准协议,兼容性好 |
这段时间在网上搜了大量的C#连接FX5U的资源,大多都是积分下载图片,图片扫码收费。那在这里就给大家提供一个我用AI写的一个winform程序案例,通过MX Component库,实现C#与FX5U之间的通讯。
C#实现三菱FX5U PLC通信(基于MC协议 (SLMP/3E帧) - 原生TCP/IP)
上篇文章已经给大家提供了通过MC协议即原生TCP/IP与FX5U进行通讯。MC协议虽然支持多地址的批量读写,但是MC协议无法完成与GX WORK3自带的 GX Simulator3实现通讯,只能与实体PLC完成通讯。
那么通过三菱官方支持的MX Component库可以很好的解决这个问题,GX Simulator3 模拟 PLC 的“身体和大脑”(执行程序逻辑),而 MX Component 则模拟连接这个“虚拟PLC”的“通信电缆和协议”。 这样,就可以在没有任何实体PLC硬件的情况下,完整地测试上位机软件。
如上图所示,这是程序的使用页面,里面包含了单点操作、批量读取、批量写入、多地址读取,唯一不好的地方是X、Y、M不支持批量写入,MXComponent似乎只支持字的批量写入,而不支持位的批量写入。
在使用本程序之前请先安装MX Component,三菱官网下载即可,安装教程可以自行网上搜索,其中也包含通用的序列号。
安装完成后,打开Communication Settings Utility,点击Wizard...
输入你的逻辑站号Logical station number,设置1,因为在winform程序代码中我设置的为1.
如果你需要设置为其他的站号,请同步修改C#代码中的内容。
private void btnConnect_Click(object sender, EventArgs e) { //请同步修改LogicalStationNumber,保持与MX Component一致 plc.ActLogicalStationNumber = 1; int r = plc.Open(); if (r == 0) { connected = true; MessageBox.Show("PLC 连接成功"); UpdateConnectionStatus(true); } else { MessageBox.Show("连接失败:" + r); UpdateConnectionStatus(false); } }设置完成后点击Next,如果已经设置过,则会弹出窗口选择,选择是即可。
在页面中,设置通讯,如果需要连接GX Simulator3,则在PC side I/F选择GX Simulator3。
在如果需要通过以太网连接FX5U则在PC side I/F选择Ethernet board,Connect module选择CPU module(FX5)。
点击next,在下一个页面中设置你的连接方式,交换机或网络直连。我测试时使用的网线直连(但也都插在交换机上),勾选Ethernet port direct connection,在下面的Select PC side adapter中选择你的网卡,选完你可以看到你的本机ip,确保与你的实体PLC能ping通即可。
设置完实体PLC或GX Simulator3后,点击next,为你的方案设置一个名称,随意设置即可。
设置完成点击Finish,点击Communication test,进入页面后,点击test,测试与实体PLC或GX Simulator3的通讯。如果连接成功会弹出下列窗口,点击确定后,将Communication Settings Utility缩小,请勿关闭。
打开winform程序,点击连接PLC,根据需求进行读取写入使用。
下面是程序源码
Form1.cs
using System; using System.Collections.Generic; using System.Windows.Forms; using ActUtlTypeLib; namespace CSharpFx5u { public partial class Form1 : Form { private ActUtlType plc = new ActUtlType(); private bool connected = false; private List<int> readBuffer = new List<int>(); // 数据类型定义 - 修复重复值问题 public enum DataType { Bool = 0, // 布尔类型 Int16 = 1, // 16位整数 Float = 2, // 32位浮点数 Double = 3 // 64位双精度浮点数 } // 元件类型定义 public enum DeviceType { Bit, // 位元件 (X, Y, M) Word // 字元件 (D, W, R) } public Form1() { InitializeComponent(); InitializeDataTypes(); } private void InitializeDataTypes() { // 初始化批量读取数据类型下拉列表 cmbBatchDataType.Items.AddRange(new object[] { "Int16", "Float", "Double", "Bool" }); cmbBatchDataType.SelectedIndex = 0; // 初始化批量写入数据类型下拉列表 cmbBatchWriteDataType.Items.AddRange(new object[] { "Int16", "Float", "Double", "Bool" }); cmbBatchWriteDataType.SelectedIndex = 0; } private void btnConnect_Click(object sender, EventArgs e) { plc.ActLogicalStationNumber = 1; int r = plc.Open(); if (r == 0) { connected = true; MessageBox.Show("PLC 连接成功"); UpdateConnectionStatus(true); } else { MessageBox.Show("连接失败:" + r); UpdateConnectionStatus(false); } } private void btnDisconnect_Click(object sender, EventArgs e) { if (connected) { plc.Close(); connected = false; MessageBox.Show("已断开 PLC"); UpdateConnectionStatus(false); } } private void UpdateConnectionStatus(bool isConnected) { lblConnectionStatus.Text = isConnected ? "状态: 已连接" : "状态: 未连接"; lblConnectionStatus.ForeColor = isConnected ? System.Drawing.Color.Green : System.Drawing.Color.Red; } private void btnReadBool_Click(object sender, EventArgs e) { if (!CheckConnection()) return; int val; int r = plc.GetDevice(txtAddress.Text, out val); if (r == 0) txtValue.Text = (val != 0).ToString(); else MessageBox.Show("读取失败:" + r); } private void btnWriteBool_Click(object sender, EventArgs e) { if (!CheckConnection()) return; if (!bool.TryParse(txtValue.Text, out bool v)) { MessageBox.Show("请输入有效的布尔值(true/false)"); return; } int r = plc.SetDevice(txtAddress.Text, v ? 1 : 0); if (r == 0) MessageBox.Show("写入成功"); else MessageBox.Show("写入失败:" + r); } private void btnReadInt_Click(object sender, EventArgs e) { if (!CheckConnection()) return; int val; int r = plc.GetDevice(txtAddress.Text, out val); if (r == 0) txtValue.Text = val.ToString(); else MessageBox.Show("读取失败:" + r); } private void btnWriteInt_Click(object sender, EventArgs e) { if (!CheckConnection()) return; if (!int.TryParse(txtValue.Text, out int v)) { MessageBox.Show("请输入有效的整数"); return; } int r = plc.SetDevice(txtAddress.Text, v); if (r == 0) MessageBox.Show("写入成功"); else MessageBox.Show("写入失败:" + r); } private void btnReadFloat_Click(object sender, EventArgs e) { if (!CheckConnection()) return; try { int baseAddr = int.Parse(txtAddress.Text.Substring(1)); int low, high; int r1 = plc.GetDevice($"D{baseAddr}", out low); int r2 = plc.GetDevice($"D{baseAddr + 1}", out high); if (r1 != 0 || r2 != 0) { MessageBox.Show("读取失败"); return; } byte[] raw = new byte[4]; raw[0] = (byte)(low & 0xFF); raw[1] = (byte)(low >> 8); raw[2] = (byte)(high & 0xFF); raw[3] = (byte)(high >> 8); float value = BitConverter.ToSingle(raw, 0); txtValue.Text = value.ToString("F4"); } catch (Exception ex) { MessageBox.Show($"读取浮点数出错: {ex.Message}"); } } private void btnWriteFloat_Click(object sender, EventArgs e) { if (!CheckConnection()) return; try { if (!float.TryParse(txtValue.Text, out float f)) { MessageBox.Show("请输入有效的浮点数"); return; } byte[] raw = BitConverter.GetBytes(f); int low = raw[0] | (raw[1] << 8); int high = raw[2] | (raw[3] << 8); int baseAddr = int.Parse(txtAddress.Text.Substring(1)); int r1 = plc.SetDevice($"D{baseAddr}", low); int r2 = plc.SetDevice($"D{baseAddr + 1}", high); if (r1 == 0 && r2 == 0) MessageBox.Show("写入成功"); else MessageBox.Show("写入失败"); } catch (Exception ex) { MessageBox.Show($"写入浮点数出错: {ex.Message}"); } } private void btnReadDouble_Click(object sender, EventArgs e) { if (!CheckConnection()) return; try { int baseAddr = int.Parse(txtAddress.Text.Substring(1)); int[] words = new int[4]; bool success = true; for (int i = 0; i < 4; i++) { int r = plc.GetDevice($"D{baseAddr + i}", out words[i]); if (r != 0) { success = false; break; } } if (!success) { MessageBox.Show("读取失败"); return; } byte[] raw = new byte[8]; for (int i = 0; i < 4; i++) { raw[i * 2] = (byte)(words[i] & 0xFF); raw[i * 2 + 1] = (byte)(words[i] >> 8); } double val = BitConverter.ToDouble(raw, 0); txtValue.Text = val.ToString("F6"); } catch (Exception ex) { MessageBox.Show($"读取双精度数出错: {ex.Message}"); } } private void btnWriteDouble_Click(object sender, EventArgs e) { if (!CheckConnection()) return; try { if (!double.TryParse(txtValue.Text, out double d)) { MessageBox.Show("请输入有效的双精度数"); return; } byte[] raw = BitConverter.GetBytes(d); int baseAddr = int.Parse(txtAddress.Text.Substring(1)); bool success = true; for (int i = 0; i < 4; i++) { int word = raw[i * 2] | (raw[i * 2 + 1] << 8); int r = plc.SetDevice($"D{baseAddr + i}", word); if (r != 0) { success = false; break; } } MessageBox.Show(success ? "写入成功" : "写入失败"); } catch (Exception ex) { MessageBox.Show($"写入双精度数出错: {ex.Message}"); } } // =========================== 批量读取操作 =========================== private void btnBatchRead_Click(object sender, EventArgs e) { try { if (!CheckConnection()) return; // 获取参数 string startAddress = txtBatchStartAddress.Text; if (!int.TryParse(txtBatchCount.Text, out int count) || count <= 0 || count > 1000) { MessageBox.Show("请输入有效的读取数量(1-1000)"); return; } // 清空之前的读取结果 readBuffer.Clear(); txtBatchResult.Clear(); // 判断元件类型(位元件还是字元件) DeviceType deviceType = GetDeviceType(startAddress[0]); if (deviceType == DeviceType.Bit) { // 位元件批量读取(逐个读取) BatchReadBitDevices(startAddress, count); } else { // 字元件批量读取(一次性读取) BatchReadWordDevices(startAddress, count); } } catch (Exception ex) { MessageBox.Show($"批量读取出错: {ex.Message}"); } } // 位元件批量读取(逐个读取) private void BatchReadBitDevices(string startAddress, int count) { string prefix = startAddress[0].ToString(); int baseAddr = int.Parse(startAddress.Substring(1)); int successCount = 0; int failCount = 0; txtBatchResult.AppendText($"位元件批量读取结果 - {prefix}元件,共{count}个:\r\n"); txtBatchResult.AppendText("通信方式:逐个读取(ReadDeviceBlock不支持位元件批量)\r\n"); txtBatchResult.AppendText("==========================================\r\n"); for (int i = 0; i < count; i++) { string address = $"{prefix}{baseAddr + i}"; int value; int result = plc.GetDevice(address, out value); if (result == 0) { txtBatchResult.AppendText($"{address}: {(value != 0 ? "ON" : "OFF")}\r\n"); successCount++; } else { txtBatchResult.AppendText($"{address}: 读取失败 (错误码: {result})\r\n"); failCount++; } } lblBatchResult.Text = $"结果: 成功 {successCount} 个,失败 {failCount} 个"; lblBatchResult.ForeColor = failCount == 0 ? System.Drawing.Color.Green : (successCount == 0 ? System.Drawing.Color.Red : System.Drawing.Color.Orange); } // 字元件批量读取(一次性读取) private void BatchReadWordDevices(string startAddress, int count) { // 获取数据类型 DataType dataType = GetDataTypeFromString(cmbBatchDataType.Text); int wordSize = GetWordSize(dataType); int totalPoints = count * wordSize; // 批量读取(单次通信,一次性读完) int[] buffer = new int[totalPoints]; int result = plc.ReadDeviceBlock(startAddress, totalPoints, out buffer[0]); if (result == 0) { // 显示读取结果(按数据类型转换) DisplayBatchResults(startAddress, count, dataType, buffer, totalPoints); readBuffer.AddRange(buffer); lblBatchResult.Text = $"结果: 成功读取 {count} 个{GetDataTypeDisplayName(dataType)}类型数据"; lblBatchResult.ForeColor = System.Drawing.Color.Green; // 显示通信信息 ShowCommunicationInfo(count, dataType, totalPoints); } else { lblBatchResult.Text = $"结果: 读取失败 (错误码: {result})"; lblBatchResult.ForeColor = System.Drawing.Color.Red; MessageBox.Show($"批量读取失败,错误码: {result}"); } } // 获取元件类型 private DeviceType GetDeviceType(char deviceChar) { char upperChar = char.ToUpper(deviceChar); // 位元件 if (upperChar == 'X' || upperChar == 'Y' || upperChar == 'M' || upperChar == 'L' || upperChar == 'F' || upperChar == 'V' || upperChar == 'B' || upperChar == 'S' || upperChar == 'T' || upperChar == 'C') { return DeviceType.Bit; } // 字元件 if (upperChar == 'D' || upperChar == 'W' || upperChar == 'R' || upperChar == 'Z' || upperChar == 'U' || upperChar == 'G') { return DeviceType.Word; } // 默认按字元件处理 return DeviceType.Word; } // 获取数据类型对应的字大小 private int GetWordSize(DataType dataType) { switch (dataType) { case DataType.Bool: return 1; case DataType.Int16: return 1; case DataType.Float: return 2; case DataType.Double: return 4; default: return 1; } } // 获取数据类型的显示名称 private string GetDataTypeDisplayName(DataType dataType) { switch (dataType) { case DataType.Bool: return "布尔"; case DataType.Int16: return "16位整数"; case DataType.Float: return "浮点数"; case DataType.Double: return "双精度浮点数"; default: return "16位整数"; } } // 显示批量读取结果(字元件) private void DisplayBatchResults(string startAddress, int count, DataType dataType, int[] buffer, int totalPoints) { int wordSize = GetWordSize(dataType); string prefix = startAddress.Substring(0, 1); int baseAddr = int.Parse(startAddress.Substring(1)); txtBatchResult.AppendText($"批量读取结果 - {GetDataTypeDisplayName(dataType)},共{count}个数据:\r\n"); txtBatchResult.AppendText("通信方式:一次性连续读取\r\n"); txtBatchResult.AppendText($"读取地址范围:{prefix}{baseAddr} ~ {prefix}{baseAddr + totalPoints - 1}\r\n"); txtBatchResult.AppendText("==========================================\r\n"); for (int i = 0; i < count; i++) { string address = $"{prefix}{baseAddr + i * wordSize}"; int dataIndex = i * wordSize; object value = ConvertBufferToValue(buffer, dataIndex, dataType); txtBatchResult.AppendText($"{address}: {value}\r\n"); } } // 将缓冲区数据转换为对应类型的值 private object ConvertBufferToValue(int[] buffer, int startIndex, DataType dataType) { try { switch (dataType) { case DataType.Bool: return buffer[startIndex] != 0; case DataType.Int16: return (short)buffer[startIndex]; case DataType.Float: if (startIndex + 1 >= buffer.Length) return 0f; byte[] floatBytes = new byte[4]; floatBytes[0] = (byte)(buffer[startIndex] & 0xFF); floatBytes[1] = (byte)(buffer[startIndex] >> 8); floatBytes[2] = (byte)(buffer[startIndex + 1] & 0xFF); floatBytes[3] = (byte)(buffer[startIndex + 1] >> 8); return BitConverter.ToSingle(floatBytes, 0); case DataType.Double: if (startIndex + 3 >= buffer.Length) return 0.0; byte[] doubleBytes = new byte[8]; for (int j = 0; j < 4; j++) { doubleBytes[j * 2] = (byte)(buffer[startIndex + j] & 0xFF); doubleBytes[j * 2 + 1] = (byte)(buffer[startIndex + j] >> 8); } return BitConverter.ToDouble(doubleBytes, 0); default: return buffer[startIndex]; } } catch { return "转换错误"; } } // =========================== 批量写入操作 =========================== private void btnBatchWrite_Click(object sender, EventArgs e) { try { if (!CheckConnection()) return; // 获取参数 string startAddress = txtBatchWriteAddress.Text; string inputData = txtBatchWriteData.Text.Trim(); if (string.IsNullOrEmpty(inputData)) { MessageBox.Show("请输入要写入的数据"); return; } // 判断元件类型(位元件还是字元件) DeviceType deviceType = GetDeviceType(startAddress[0]); if (deviceType == DeviceType.Bit) { // 位元件批量写入(逐个写入) BatchWriteBitDevices(startAddress, inputData); } else { // 字元件批量写入(一次性写入) BatchWriteWordDevices(startAddress, inputData); } } catch (Exception ex) { MessageBox.Show($"批量写入出错: {ex.Message}"); } } // 位元件批量写入(逐个写入) private void BatchWriteBitDevices(string startAddress, string inputData) { string[] parts = inputData.Split(new[] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); string prefix = startAddress[0].ToString(); int baseAddr = int.Parse(startAddress.Substring(1)); int successCount = 0; int failCount = 0; lblBatchWriteResult.Text = "写入中..."; // 逐个写入位元件 for (int i = 0; i < parts.Length; i++) { if (i >= 1000) break; // 限制最多1000个 string address = $"{prefix}{baseAddr + i}"; string part = parts[i].Trim(); if (string.IsNullOrEmpty(part)) continue; // 解析数据:0/1 或 false/true int value; if (int.TryParse(part, out value)) { value = (value != 0) ? 1 : 0; } else if (bool.TryParse(part, out bool boolVal)) { value = boolVal ? 1 : 0; } else { failCount++; continue; } int result = plc.SetDevice(address, value); if (result == 0) { successCount++; } else { failCount++; } } lblBatchWriteResult.Text = $"结果: 成功 {successCount} 个,失败 {failCount} 个"; lblBatchWriteResult.ForeColor = failCount == 0 ? System.Drawing.Color.Green : (successCount == 0 ? System.Drawing.Color.Red : System.Drawing.Color.Orange); } // 字元件批量写入(一次性写入) private void BatchWriteWordDevices(string startAddress, string inputData) { DataType dataType = GetDataTypeFromString(cmbBatchWriteDataType.Text); int wordSize = GetWordSize(dataType); // 解析输入数据 List<object> values = ParseInputData(inputData, dataType); int count = values.Count; int totalPoints = count * wordSize; // 准备写入数组 int[] writeData = new int[totalPoints]; bool success = ConvertValuesToBuffer(values, dataType, writeData); if (!success) { MessageBox.Show("数据格式转换失败"); return; } // 批量写入(单次通信,一次性写完) int result = plc.WriteDeviceBlock(startAddress, totalPoints, ref writeData[0]); if (result == 0) { lblBatchWriteResult.Text = $"结果: 成功写入 {count} 个{GetDataTypeDisplayName(dataType)}类型数据"; lblBatchWriteResult.ForeColor = System.Drawing.Color.Green; // 显示通信信息 ShowWriteCommunicationInfo(count, dataType, totalPoints); } else { lblBatchWriteResult.Text = $"结果: 写入失败 (错误码: {result})"; lblBatchWriteResult.ForeColor = System.Drawing.Color.Red; MessageBox.Show($"批量写入失败,错误码: {result}"); } } // 解析输入字符串为对应类型的值列表 private List<object> ParseInputData(string input, DataType dataType) { List<object> values = new List<object>(); string[] parts = input.Split(new[] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); foreach (string part in parts) { string trimmed = part.Trim(); if (string.IsNullOrEmpty(trimmed)) continue; try { switch (dataType) { case DataType.Bool: values.Add(bool.Parse(trimmed)); break; case DataType.Int16: values.Add(short.Parse(trimmed)); break; case DataType.Float: values.Add(float.Parse(trimmed)); break; case DataType.Double: values.Add(double.Parse(trimmed)); break; } } catch { // 如果解析失败,使用默认值 switch (dataType) { case DataType.Bool: values.Add(false); break; case DataType.Int16: values.Add((short)0); break; case DataType.Float: values.Add(0f); break; case DataType.Double: values.Add(0.0); break; } } } return values; } // 将值列表转换为缓冲区 private bool ConvertValuesToBuffer(List<object> values, DataType dataType, int[] buffer) { try { int wordSize = GetWordSize(dataType); int bufferIndex = 0; foreach (object value in values) { switch (dataType) { case DataType.Bool: bool boolVal = (bool)value; buffer[bufferIndex++] = boolVal ? 1 : 0; break; case DataType.Int16: short shortVal = (short)value; buffer[bufferIndex++] = shortVal; break; case DataType.Float: float floatVal = (float)value; byte[] floatBytes = BitConverter.GetBytes(floatVal); buffer[bufferIndex++] = floatBytes[0] | (floatBytes[1] << 8); buffer[bufferIndex++] = floatBytes[2] | (floatBytes[3] << 8); break; case DataType.Double: double doubleVal = (double)value; byte[] doubleBytes = BitConverter.GetBytes(doubleVal); for (int i = 0; i < 4; i++) { buffer[bufferIndex++] = doubleBytes[i * 2] | (doubleBytes[i * 2 + 1] << 8); } break; } } return true; } catch { return false; } } // 从字符串获取数据类型 private DataType GetDataTypeFromString(string typeStr) { switch (typeStr.ToLower()) { case "bool": return DataType.Bool; case "int16": return DataType.Int16; case "float": return DataType.Float; case "double": return DataType.Double; default: return DataType.Int16; } } // =========================== 示例和工具方法 =========================== private void btnExampleRead10_Click(object sender, EventArgs e) { txtBatchStartAddress.Text = "D0"; txtBatchCount.Text = "10"; cmbBatchDataType.SelectedItem = "Int16"; btnBatchRead.PerformClick(); } private void btnExampleWrite10_Click(object sender, EventArgs e) { txtBatchWriteAddress.Text = "D100"; txtBatchWriteData.Text = "1,2,3,4,5,6,7,8,9,10"; cmbBatchWriteDataType.SelectedItem = "Int16"; btnBatchWrite.PerformClick(); } private void btnExampleReadFloat_Click(object sender, EventArgs e) { txtBatchStartAddress.Text = "D200"; txtBatchCount.Text = "5"; cmbBatchDataType.SelectedItem = "Float"; txtBatchResult.Clear(); txtBatchResult.AppendText("示例:读取5个浮点数\r\n"); txtBatchResult.AppendText("每个浮点数占用2个寄存器(D)\r\n"); txtBatchResult.AppendText("将一次性读取D200-D209共10个寄存器\r\n"); } private void btnExampleWriteFloat_Click(object sender, EventArgs e) { txtBatchWriteAddress.Text = "D300"; txtBatchWriteData.Text = "1.1, 2.2, 3.3, 4.4, 5.5"; cmbBatchWriteDataType.SelectedItem = "Float"; txtBatchWriteData.AppendText("\r\n示例:写入5个浮点数\r\n"); txtBatchWriteData.AppendText("每个浮点数占用2个寄存器(D)\r\n"); txtBatchWriteData.AppendText("将一次性写入D300-D309共10个寄存器\r\n"); } // 示例:读取位元件 private void btnExampleReadBits_Click(object sender, EventArgs e) { txtBatchStartAddress.Text = "X0"; txtBatchCount.Text = "10"; txtBatchResult.Clear(); txtBatchResult.AppendText("示例:读取10个位元件(X0-X9)\r\n"); txtBatchResult.AppendText("注意:位元件只能逐个读取\r\n"); txtBatchResult.AppendText("不支持一次性批量读取\r\n"); } // 示例:写入位元件 private void btnExampleWriteBits_Click(object sender, EventArgs e) { txtBatchWriteAddress.Text = "M0"; txtBatchWriteData.Text = "1,0,1,0,1,0,1,0,1,0"; txtBatchWriteData.AppendText("\r\n示例:写入10个位元件(M0-M9)\r\n"); txtBatchWriteData.AppendText("注意:位元件只能逐个写入\r\n"); txtBatchWriteData.AppendText("不支持一次性批量写入\r\n"); } // 清空批量读取结果 private void btnClearBatchResult_Click(object sender, EventArgs e) { txtBatchResult.Clear(); } // 清空多地址读取结果 private void btnClearMultiResult_Click(object sender, EventArgs e) { txtMultiAddressResult.Clear(); txtMultiAddressWriteResult.Clear(); } // 测试所有批量功能 private void btnTestAll_Click(object sender, EventArgs e) { if (!CheckConnection()) return; try { // 测试批量读取(字元件) txtBatchStartAddress.Text = "D0"; txtBatchCount.Text = "5"; cmbBatchDataType.SelectedItem = "Int16"; btnBatchRead.PerformClick(); System.Threading.Thread.Sleep(100); // 测试批量写入(字元件) txtBatchWriteAddress.Text = "D100"; txtBatchWriteData.Text = "100,200,300,400,500"; cmbBatchWriteDataType.SelectedItem = "Int16"; btnBatchWrite.PerformClick(); // 测试批量读取(位元件) txtBatchStartAddress.Text = "X0"; txtBatchCount.Text = "8"; System.Threading.Thread.Sleep(100); btnBatchRead.PerformClick(); MessageBox.Show("批量功能测试完成"); } catch (Exception ex) { MessageBox.Show($"测试过程中出错: {ex.Message}"); } } // 多地址读取功能 private void btnMultiAddressRead_Click(object sender, EventArgs e) { try { if (!CheckConnection()) return; // 解析多个地址 string[] addresses = txtMultiAddresses.Text.Split(new[] { ',', ';', ' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); if (addresses.Length == 0) { MessageBox.Show("请输入要读取的地址"); return; } txtMultiAddressResult.Clear(); int successCount = 0; int failCount = 0; txtMultiAddressResult.AppendText($"多地址读取(逐个读取,共{addresses.Length}个地址):\r\n"); txtMultiAddressResult.AppendText("通信方式:多个独立通信\r\n"); txtMultiAddressResult.AppendText("================================\r\n"); // 逐个读取多个地址(多个独立通信) for (int i = 0; i < addresses.Length; i++) { string address = addresses[i].Trim(); if (string.IsNullOrEmpty(address)) continue; int value; int result = plc.GetDevice(address, out value); if (result == 0) { // 判断是否为位元件 char firstChar = address[0]; if (GetDeviceType(firstChar) == DeviceType.Bit) { txtMultiAddressResult.AppendText($"{address}: {(value != 0 ? "ON" : "OFF")}\r\n"); } else { txtMultiAddressResult.AppendText($"{address}: {value}\r\n"); } successCount++; } else { txtMultiAddressResult.AppendText($"{address}: 读取失败 (错误码: {result})\r\n"); failCount++; } } lblMultiAddressResult.Text = $"结果: 成功 {successCount} 个,失败 {failCount} 个"; lblMultiAddressResult.ForeColor = failCount == 0 ? System.Drawing.Color.Green : (successCount == 0 ? System.Drawing.Color.Red : System.Drawing.Color.Orange); } catch (Exception ex) { MessageBox.Show($"多地址读取出错: {ex.Message}"); } } // 多地址写入功能 private void btnMultiAddressWrite_Click(object sender, EventArgs e) { try { if (!CheckConnection()) return; // 解析地址和值对(格式:D0=100,M0=1,X0=1) string[] pairs = txtMultiAddressWriteData.Text.Split(new[] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); if (pairs.Length == 0) { MessageBox.Show("请输入要写入的地址和数据"); return; } int successCount = 0; int failCount = 0; txtMultiAddressWriteResult.Clear(); txtMultiAddressWriteResult.AppendText($"多地址写入(逐个写入,共{pairs.Length}个数据):\r\n"); txtMultiAddressWriteResult.AppendText("通信方式:多个独立通信\r\n"); txtMultiAddressWriteResult.AppendText("================================\r\n"); // 逐个写入多个地址(多个独立通信) for (int i = 0; i < pairs.Length; i++) { string pair = pairs[i].Trim(); if (string.IsNullOrEmpty(pair)) continue; string[] parts = pair.Split('='); if (parts.Length != 2) { txtMultiAddressWriteResult.AppendText($"格式错误: {pair}\r\n"); failCount++; continue; } string address = parts[0].Trim(); string valueStr = parts[1].Trim(); // 判断是否为位元件 char firstChar = address[0]; int value; if (GetDeviceType(firstChar) == DeviceType.Bit) { // 位元件:接受0/1或true/false if (int.TryParse(valueStr, out int intVal)) { value = (intVal != 0) ? 1 : 0; } else if (bool.TryParse(valueStr, out bool boolVal)) { value = boolVal ? 1 : 0; } else { txtMultiAddressWriteResult.AppendText($"数据格式错误: {pair}\r\n"); failCount++; continue; } } else { // 字元件:只接受整数 if (!int.TryParse(valueStr, out value)) { txtMultiAddressWriteResult.AppendText($"数据格式错误: {pair}\r\n"); failCount++; continue; } } int result = plc.SetDevice(address, value); if (result == 0) { txtMultiAddressWriteResult.AppendText($"成功: {address} = {value}\r\n"); successCount++; } else { txtMultiAddressWriteResult.AppendText($"失败: {address} = {value} (错误码: {result})\r\n"); failCount++; } } lblMultiAddressWriteResult.Text = $"结果: 成功 {successCount} 个,失败 {failCount} 个"; lblMultiAddressWriteResult.ForeColor = failCount == 0 ? System.Drawing.Color.Green : (successCount == 0 ? System.Drawing.Color.Red : System.Drawing.Color.Orange); } catch (Exception ex) { MessageBox.Show($"多地址写入出错: {ex.Message}"); } } // 辅助方法:检查连接状态 private bool CheckConnection() { if (!connected) { MessageBox.Show("请先连接PLC"); return false; } return true; } // 显示读取通信信息 private void ShowCommunicationInfo(int count, DataType dataType, int totalPoints) { string info = $"通信信息:\r\n"; info += $"数据类型:{GetDataTypeDisplayName(dataType)}\r\n"; info += $"数据个数:{count}\r\n"; info += $"占用寄存器数:{totalPoints}个\r\n"; info += $"通信方式:一次性批量读取\r\n"; info += $"效率对比:相比逐个读取减少{count - 1}次通信\r\n"; txtBatchResult.AppendText("\r\n" + info); } // 显示写入通信信息 private void ShowWriteCommunicationInfo(int count, DataType dataType, int totalPoints) { string info = $"通信信息:\r\n"; info += $"数据类型:{GetDataTypeDisplayName(dataType)}\r\n"; info += $"数据个数:{count}\r\n"; info += $"占用寄存器数:{totalPoints}个\r\n"; info += $"通信方式:一次性批量写入\r\n"; info += $"效率对比:相比逐个写入减少{count - 1}次通信\r\n"; txtBatchWriteData.AppendText("\r\n" + info); } // 批量读取说明 private void btnBatchReadHelp_Click(object sender, EventArgs e) { string help = "批量读取说明:\r\n" + "1. 位元件(X,Y,M等):只能逐个读取,不支持一次性批量\r\n" + "2. 字元件(D,W等):支持一次性批量读取\r\n" + "3. 字元件数据类型:\r\n" + " - Int16/Bool: 1个寄存器\r\n" + " - Float: 2个寄存器\r\n" + " - Double: 4个寄存器\r\n" + "4. 位元件自动识别,无需选择数据类型"; MessageBox.Show(help, "批量读取说明", MessageBoxButtons.OK, MessageBoxIcon.Information); } // 批量写入说明 private void btnBatchWriteHelp_Click(object sender, EventArgs e) { string help = "批量写入说明:\r\n" + "1. 位元件(X,Y,M等):只能逐个写入,不支持一次性批量\r\n" + "2. 字元件(D,W等):支持一次性批量写入\r\n" + "3. 位元件数据格式:0/1 或 true/false\r\n" + "4. 字元件数据格式:根据数据类型输入对应值\r\n" + "5. 数据分隔符:逗号、分号或换行"; MessageBox.Show(help, "批量写入说明", MessageBoxButtons.OK, MessageBoxIcon.Information); } } }Form1.Designer.cs
namespace CSharpFx5u { partial class Form1 { private System.ComponentModel.IContainer components = null; protected override void Dispose(bool disposing) { if (disposing && (components != null)) components.Dispose(); base.Dispose(disposing); } #region Windows Form Designer generated code private void InitializeComponent() { this.btnConnect = new System.Windows.Forms.Button(); this.btnDisconnect = new System.Windows.Forms.Button(); this.txtAddress = new System.Windows.Forms.TextBox(); this.txtValue = new System.Windows.Forms.TextBox(); this.btnReadBool = new System.Windows.Forms.Button(); this.btnWriteBool = new System.Windows.Forms.Button(); this.btnReadInt = new System.Windows.Forms.Button(); this.btnWriteInt = new System.Windows.Forms.Button(); this.btnReadFloat = new System.Windows.Forms.Button(); this.btnWriteFloat = new System.Windows.Forms.Button(); this.btnReadDouble = new System.Windows.Forms.Button(); this.btnWriteDouble = new System.Windows.Forms.Button(); this.lblAddr = new System.Windows.Forms.Label(); this.lblValue = new System.Windows.Forms.Label(); this.lblConnectionStatus = new System.Windows.Forms.Label(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.btnBatchReadHelp = new System.Windows.Forms.Button(); this.cmbBatchDataType = new System.Windows.Forms.ComboBox(); this.lblBatchDataType = new System.Windows.Forms.Label(); this.txtBatchStartAddress = new System.Windows.Forms.TextBox(); this.txtBatchCount = new System.Windows.Forms.TextBox(); this.btnBatchRead = new System.Windows.Forms.Button(); this.lblBatchStartAddress = new System.Windows.Forms.Label(); this.lblBatchCount = new System.Windows.Forms.Label(); this.txtBatchResult = new System.Windows.Forms.TextBox(); this.lblBatchResult = new System.Windows.Forms.Label(); this.btnClearBatchResult = new System.Windows.Forms.Button(); this.btnExampleRead10 = new System.Windows.Forms.Button(); this.btnExampleReadFloat = new System.Windows.Forms.Button(); this.groupBox3 = new System.Windows.Forms.GroupBox(); this.btnBatchWriteHelp = new System.Windows.Forms.Button(); this.btnExampleWriteFloat = new System.Windows.Forms.Button(); this.btnExampleWrite10 = new System.Windows.Forms.Button(); this.lblBatchWriteResult = new System.Windows.Forms.Label(); this.btnBatchWrite = new System.Windows.Forms.Button(); this.txtBatchWriteData = new System.Windows.Forms.TextBox(); this.txtBatchWriteAddress = new System.Windows.Forms.TextBox(); this.lblBatchWriteData = new System.Windows.Forms.Label(); this.lblBatchWriteAddress = new System.Windows.Forms.Label(); this.cmbBatchWriteDataType = new System.Windows.Forms.ComboBox(); this.lblBatchWriteDataType = new System.Windows.Forms.Label(); this.groupBox4 = new System.Windows.Forms.GroupBox(); this.btnClearMultiResult = new System.Windows.Forms.Button(); this.lblMultiAddressResult = new System.Windows.Forms.Label(); this.txtMultiAddressResult = new System.Windows.Forms.TextBox(); this.btnMultiAddressRead = new System.Windows.Forms.Button(); this.txtMultiAddresses = new System.Windows.Forms.TextBox(); this.lblMultiAddresses = new System.Windows.Forms.Label(); this.groupBox5 = new System.Windows.Forms.GroupBox(); this.lblMultiAddressWriteResult = new System.Windows.Forms.Label(); this.txtMultiAddressWriteResult = new System.Windows.Forms.TextBox(); this.btnMultiAddressWrite = new System.Windows.Forms.Button(); this.txtMultiAddressWriteData = new System.Windows.Forms.TextBox(); this.lblMultiAddressWriteData = new System.Windows.Forms.Label(); this.btnTestAll = new System.Windows.Forms.Button(); this.btnExampleReadBits = new System.Windows.Forms.Button(); this.btnExampleWriteBits = new System.Windows.Forms.Button(); this.groupBox1.SuspendLayout(); this.groupBox2.SuspendLayout(); this.groupBox3.SuspendLayout(); this.groupBox4.SuspendLayout(); this.groupBox5.SuspendLayout(); this.SuspendLayout(); // // btnConnect // this.btnConnect.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(192))))); this.btnConnect.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.btnConnect.Location = new System.Drawing.Point(20, 18); this.btnConnect.Name = "btnConnect"; this.btnConnect.Size = new System.Drawing.Size(100, 32); this.btnConnect.TabIndex = 0; this.btnConnect.Text = "连接PLC"; this.btnConnect.UseVisualStyleBackColor = false; this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click); // // btnDisconnect // this.btnDisconnect.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(192))))); this.btnDisconnect.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.btnDisconnect.Location = new System.Drawing.Point(130, 18); this.btnDisconnect.Name = "btnDisconnect"; this.btnDisconnect.Size = new System.Drawing.Size(100, 32); this.btnDisconnect.TabIndex = 1; this.btnDisconnect.Text = "断开PLC"; this.btnDisconnect.UseVisualStyleBackColor = false; this.btnDisconnect.Click += new System.EventHandler(this.btnDisconnect_Click); // // txtAddress // this.txtAddress.Location = new System.Drawing.Point(90, 23); this.txtAddress.Name = "txtAddress"; this.txtAddress.Size = new System.Drawing.Size(100, 21); this.txtAddress.TabIndex = 2; this.txtAddress.Text = "D0"; // // txtValue // this.txtValue.Location = new System.Drawing.Point(90, 51); this.txtValue.Name = "txtValue"; this.txtValue.Size = new System.Drawing.Size(100, 21); this.txtValue.TabIndex = 3; this.txtValue.Text = "0"; // // btnReadBool // this.btnReadBool.Location = new System.Drawing.Point(15, 83); this.btnReadBool.Name = "btnReadBool"; this.btnReadBool.Size = new System.Drawing.Size(80, 28); this.btnReadBool.TabIndex = 4; this.btnReadBool.Text = "读取 Bool"; this.btnReadBool.UseVisualStyleBackColor = true; this.btnReadBool.Click += new System.EventHandler(this.btnReadBool_Click); // // btnWriteBool // this.btnWriteBool.Location = new System.Drawing.Point(110, 83); this.btnWriteBool.Name = "btnWriteBool"; this.btnWriteBool.Size = new System.Drawing.Size(80, 28); this.btnWriteBool.TabIndex = 5; this.btnWriteBool.Text = "写入 Bool"; this.btnWriteBool.UseVisualStyleBackColor = true; this.btnWriteBool.Click += new System.EventHandler(this.btnWriteBool_Click); // // btnReadInt // this.btnReadInt.Location = new System.Drawing.Point(15, 120); this.btnReadInt.Name = "btnReadInt"; this.btnReadInt.Size = new System.Drawing.Size(80, 28); this.btnReadInt.TabIndex = 6; this.btnReadInt.Text = "读取 Int"; this.btnReadInt.UseVisualStyleBackColor = true; this.btnReadInt.Click += new System.EventHandler(this.btnReadInt_Click); // // btnWriteInt // this.btnWriteInt.Location = new System.Drawing.Point(110, 120); this.btnWriteInt.Name = "btnWriteInt"; this.btnWriteInt.Size = new System.Drawing.Size(80, 28); this.btnWriteInt.TabIndex = 7; this.btnWriteInt.Text = "写入 Int"; this.btnWriteInt.UseVisualStyleBackColor = true; this.btnWriteInt.Click += new System.EventHandler(this.btnWriteInt_Click); // // btnReadFloat // this.btnReadFloat.Location = new System.Drawing.Point(15, 157); this.btnReadFloat.Name = "btnReadFloat"; this.btnReadFloat.Size = new System.Drawing.Size(80, 28); this.btnReadFloat.TabIndex = 8; this.btnReadFloat.Text = "读取 Float"; this.btnReadFloat.UseVisualStyleBackColor = true; this.btnReadFloat.Click += new System.EventHandler(this.btnReadFloat_Click); // // btnWriteFloat // this.btnWriteFloat.Location = new System.Drawing.Point(110, 157); this.btnWriteFloat.Name = "btnWriteFloat"; this.btnWriteFloat.Size = new System.Drawing.Size(80, 28); this.btnWriteFloat.TabIndex = 9; this.btnWriteFloat.Text = "写入 Float"; this.btnWriteFloat.UseVisualStyleBackColor = true; this.btnWriteFloat.Click += new System.EventHandler(this.btnWriteFloat_Click); // // btnReadDouble // this.btnReadDouble.Location = new System.Drawing.Point(15, 194); this.btnReadDouble.Name = "btnReadDouble"; this.btnReadDouble.Size = new System.Drawing.Size(80, 28); this.btnReadDouble.TabIndex = 10; this.btnReadDouble.Text = "读取 Double"; this.btnReadDouble.UseVisualStyleBackColor = true; this.btnReadDouble.Click += new System.EventHandler(this.btnReadDouble_Click); // // btnWriteDouble // this.btnWriteDouble.Location = new System.Drawing.Point(110, 194); this.btnWriteDouble.Name = "btnWriteDouble"; this.btnWriteDouble.Size = new System.Drawing.Size(80, 28); this.btnWriteDouble.TabIndex = 11; this.btnWriteDouble.Text = "写入 Double"; this.btnWriteDouble.UseVisualStyleBackColor = true; this.btnWriteDouble.Click += new System.EventHandler(this.btnWriteDouble_Click); // // lblAddr // this.lblAddr.AutoSize = true; this.lblAddr.Location = new System.Drawing.Point(15, 26); this.lblAddr.Name = "lblAddr"; this.lblAddr.Size = new System.Drawing.Size(59, 12); this.lblAddr.TabIndex = 12; this.lblAddr.Text = "设备地址:"; // // lblValue // this.lblValue.AutoSize = true; this.lblValue.Location = new System.Drawing.Point(15, 54); this.lblValue.Name = "lblValue"; this.lblValue.Size = new System.Drawing.Size(35, 12); this.lblValue.TabIndex = 13; this.lblValue.Text = "数值:"; // // lblConnectionStatus // this.lblConnectionStatus.AutoSize = true; this.lblConnectionStatus.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.lblConnectionStatus.Location = new System.Drawing.Point(250, 28); this.lblConnectionStatus.Name = "lblConnectionStatus"; this.lblConnectionStatus.Size = new System.Drawing.Size(80, 15); this.lblConnectionStatus.TabIndex = 14; this.lblConnectionStatus.Text = "状态: 未连接"; // // groupBox1 // this.groupBox1.Controls.Add(this.lblAddr); this.groupBox1.Controls.Add(this.lblValue); this.groupBox1.Controls.Add(this.txtAddress); this.groupBox1.Controls.Add(this.txtValue); this.groupBox1.Controls.Add(this.btnWriteDouble); this.groupBox1.Controls.Add(this.btnReadBool); this.groupBox1.Controls.Add(this.btnReadDouble); this.groupBox1.Controls.Add(this.btnWriteBool); this.groupBox1.Controls.Add(this.btnWriteFloat); this.groupBox1.Controls.Add(this.btnReadInt); this.groupBox1.Controls.Add(this.btnReadFloat); this.groupBox1.Controls.Add(this.btnWriteInt); this.groupBox1.Location = new System.Drawing.Point(20, 65); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(210, 240); this.groupBox1.TabIndex = 15; this.groupBox1.TabStop = false; this.groupBox1.Text = "单点操作"; // // groupBox2 // this.groupBox2.Controls.Add(this.btnBatchReadHelp); this.groupBox2.Controls.Add(this.cmbBatchDataType); this.groupBox2.Controls.Add(this.lblBatchDataType); this.groupBox2.Controls.Add(this.txtBatchStartAddress); this.groupBox2.Controls.Add(this.txtBatchCount); this.groupBox2.Controls.Add(this.btnBatchRead); this.groupBox2.Controls.Add(this.lblBatchStartAddress); this.groupBox2.Controls.Add(this.lblBatchCount); this.groupBox2.Controls.Add(this.txtBatchResult); this.groupBox2.Controls.Add(this.lblBatchResult); this.groupBox2.Controls.Add(this.btnClearBatchResult); this.groupBox2.Controls.Add(this.btnExampleRead10); this.groupBox2.Controls.Add(this.btnExampleReadFloat); this.groupBox2.Location = new System.Drawing.Point(250, 65); this.groupBox2.Name = "groupBox2"; this.groupBox2.Size = new System.Drawing.Size(350, 240); this.groupBox2.TabIndex = 16; this.groupBox2.TabStop = false; this.groupBox2.Text = "批量读取(一次性通信)"; // // btnBatchReadHelp // this.btnBatchReadHelp.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.btnBatchReadHelp.Location = new System.Drawing.Point(180, 78); this.btnBatchReadHelp.Name = "btnBatchReadHelp"; this.btnBatchReadHelp.Size = new System.Drawing.Size(30, 19); this.btnBatchReadHelp.TabIndex = 15; this.btnBatchReadHelp.Text = "?"; this.btnBatchReadHelp.UseVisualStyleBackColor = true; this.btnBatchReadHelp.Click += new System.EventHandler(this.btnBatchReadHelp_Click); // // cmbBatchDataType // this.cmbBatchDataType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbBatchDataType.FormattingEnabled = true; this.cmbBatchDataType.Location = new System.Drawing.Point(95, 78); this.cmbBatchDataType.Name = "cmbBatchDataType"; this.cmbBatchDataType.Size = new System.Drawing.Size(80, 20); this.cmbBatchDataType.TabIndex = 14; // // lblBatchDataType // this.lblBatchDataType.AutoSize = true; this.lblBatchDataType.Location = new System.Drawing.Point(15, 81); this.lblBatchDataType.Name = "lblBatchDataType"; this.lblBatchDataType.Size = new System.Drawing.Size(59, 12); this.lblBatchDataType.TabIndex = 13; this.lblBatchDataType.Text = "数据类型:"; // // txtBatchStartAddress // this.txtBatchStartAddress.Location = new System.Drawing.Point(95, 23); this.txtBatchStartAddress.Name = "txtBatchStartAddress"; this.txtBatchStartAddress.Size = new System.Drawing.Size(70, 21); this.txtBatchStartAddress.TabIndex = 0; this.txtBatchStartAddress.Text = "D0"; // // txtBatchCount // this.txtBatchCount.Location = new System.Drawing.Point(95, 51); this.txtBatchCount.Name = "txtBatchCount"; this.txtBatchCount.Size = new System.Drawing.Size(70, 21); this.txtBatchCount.TabIndex = 1; this.txtBatchCount.Text = "10"; // // btnBatchRead // this.btnBatchRead.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(255))))); this.btnBatchRead.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.btnBatchRead.Location = new System.Drawing.Point(220, 18); this.btnBatchRead.Name = "btnBatchRead"; this.btnBatchRead.Size = new System.Drawing.Size(110, 28); this.btnBatchRead.TabIndex = 2; this.btnBatchRead.Text = "批量读取"; this.btnBatchRead.UseVisualStyleBackColor = false; this.btnBatchRead.Click += new System.EventHandler(this.btnBatchRead_Click); // // lblBatchStartAddress // this.lblBatchStartAddress.AutoSize = true; this.lblBatchStartAddress.Location = new System.Drawing.Point(15, 26); this.lblBatchStartAddress.Name = "lblBatchStartAddress"; this.lblBatchStartAddress.Size = new System.Drawing.Size(59, 12); this.lblBatchStartAddress.TabIndex = 3; this.lblBatchStartAddress.Text = "起始地址:"; // // lblBatchCount // this.lblBatchCount.AutoSize = true; this.lblBatchCount.Location = new System.Drawing.Point(15, 54); this.lblBatchCount.Name = "lblBatchCount"; this.lblBatchCount.Size = new System.Drawing.Size(35, 12); this.lblBatchCount.TabIndex = 4; this.lblBatchCount.Text = "数量:"; // // txtBatchResult // this.txtBatchResult.Location = new System.Drawing.Point(15, 122); this.txtBatchResult.Multiline = true; this.txtBatchResult.Name = "txtBatchResult"; this.txtBatchResult.ReadOnly = true; this.txtBatchResult.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.txtBatchResult.Size = new System.Drawing.Size(320, 111); this.txtBatchResult.TabIndex = 5; // // lblBatchResult // this.lblBatchResult.AutoSize = true; this.lblBatchResult.Location = new System.Drawing.Point(15, 105); this.lblBatchResult.Name = "lblBatchResult"; this.lblBatchResult.Size = new System.Drawing.Size(35, 12); this.lblBatchResult.TabIndex = 6; this.lblBatchResult.Text = "结果:"; // // btnClearBatchResult // this.btnClearBatchResult.Location = new System.Drawing.Point(270, 51); this.btnClearBatchResult.Name = "btnClearBatchResult"; this.btnClearBatchResult.Size = new System.Drawing.Size(65, 23); this.btnClearBatchResult.TabIndex = 7; this.btnClearBatchResult.Text = "清空"; this.btnClearBatchResult.UseVisualStyleBackColor = true; this.btnClearBatchResult.Click += new System.EventHandler(this.btnClearBatchResult_Click); // // btnExampleRead10 // this.btnExampleRead10.Location = new System.Drawing.Point(220, 51); this.btnExampleRead10.Name = "btnExampleRead10"; this.btnExampleRead10.Size = new System.Drawing.Size(50, 23); this.btnExampleRead10.TabIndex = 11; this.btnExampleRead10.Text = "整数"; this.btnExampleRead10.UseVisualStyleBackColor = true; this.btnExampleRead10.Click += new System.EventHandler(this.btnExampleRead10_Click); // // btnExampleReadFloat // this.btnExampleReadFloat.Location = new System.Drawing.Point(270, 78); this.btnExampleReadFloat.Name = "btnExampleReadFloat"; this.btnExampleReadFloat.Size = new System.Drawing.Size(65, 23); this.btnExampleReadFloat.TabIndex = 12; this.btnExampleReadFloat.Text = "浮点"; this.btnExampleReadFloat.UseVisualStyleBackColor = true; this.btnExampleReadFloat.Click += new System.EventHandler(this.btnExampleReadFloat_Click); // // groupBox3 // this.groupBox3.Controls.Add(this.btnBatchWriteHelp); this.groupBox3.Controls.Add(this.btnExampleWriteFloat); this.groupBox3.Controls.Add(this.btnExampleWrite10); this.groupBox3.Controls.Add(this.lblBatchWriteResult); this.groupBox3.Controls.Add(this.btnBatchWrite); this.groupBox3.Controls.Add(this.txtBatchWriteData); this.groupBox3.Controls.Add(this.txtBatchWriteAddress); this.groupBox3.Controls.Add(this.lblBatchWriteData); this.groupBox3.Controls.Add(this.lblBatchWriteAddress); this.groupBox3.Controls.Add(this.cmbBatchWriteDataType); this.groupBox3.Controls.Add(this.lblBatchWriteDataType); this.groupBox3.Location = new System.Drawing.Point(620, 65); this.groupBox3.Name = "groupBox3"; this.groupBox3.Size = new System.Drawing.Size(350, 240); this.groupBox3.TabIndex = 17; this.groupBox3.TabStop = false; this.groupBox3.Text = "批量写入(一次性通信)"; // // btnBatchWriteHelp // this.btnBatchWriteHelp.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.btnBatchWriteHelp.Location = new System.Drawing.Point(180, 23); this.btnBatchWriteHelp.Name = "btnBatchWriteHelp"; this.btnBatchWriteHelp.Size = new System.Drawing.Size(30, 19); this.btnBatchWriteHelp.TabIndex = 16; this.btnBatchWriteHelp.Text = "?"; this.btnBatchWriteHelp.UseVisualStyleBackColor = true; this.btnBatchWriteHelp.Click += new System.EventHandler(this.btnBatchWriteHelp_Click); // // btnExampleWriteFloat // this.btnExampleWriteFloat.Location = new System.Drawing.Point(270, 51); this.btnExampleWriteFloat.Name = "btnExampleWriteFloat"; this.btnExampleWriteFloat.Size = new System.Drawing.Size(65, 23); this.btnExampleWriteFloat.TabIndex = 15; this.btnExampleWriteFloat.Text = "浮点"; this.btnExampleWriteFloat.UseVisualStyleBackColor = true; this.btnExampleWriteFloat.Click += new System.EventHandler(this.btnExampleWriteFloat_Click); // // btnExampleWrite10 // this.btnExampleWrite10.Location = new System.Drawing.Point(220, 51); this.btnExampleWrite10.Name = "btnExampleWrite10"; this.btnExampleWrite10.Size = new System.Drawing.Size(50, 23); this.btnExampleWrite10.TabIndex = 14; this.btnExampleWrite10.Text = "整数"; this.btnExampleWrite10.UseVisualStyleBackColor = true; this.btnExampleWrite10.Click += new System.EventHandler(this.btnExampleWrite10_Click); // // lblBatchWriteResult // this.lblBatchWriteResult.AutoSize = true; this.lblBatchWriteResult.Location = new System.Drawing.Point(15, 148); this.lblBatchWriteResult.Name = "lblBatchWriteResult"; this.lblBatchWriteResult.Size = new System.Drawing.Size(35, 12); this.lblBatchWriteResult.TabIndex = 13; this.lblBatchWriteResult.Text = "结果:"; // // btnBatchWrite // this.btnBatchWrite.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(255))))); this.btnBatchWrite.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.btnBatchWrite.Location = new System.Drawing.Point(220, 18); this.btnBatchWrite.Name = "btnBatchWrite"; this.btnBatchWrite.Size = new System.Drawing.Size(110, 28); this.btnBatchWrite.TabIndex = 12; this.btnBatchWrite.Text = "批量写入"; this.btnBatchWrite.UseVisualStyleBackColor = false; this.btnBatchWrite.Click += new System.EventHandler(this.btnBatchWrite_Click); // // txtBatchWriteData // this.txtBatchWriteData.Location = new System.Drawing.Point(95, 51); this.txtBatchWriteData.Multiline = true; this.txtBatchWriteData.Name = "txtBatchWriteData"; this.txtBatchWriteData.Size = new System.Drawing.Size(120, 93); this.txtBatchWriteData.TabIndex = 11; this.txtBatchWriteData.Text = "1,2,3,4,5,6,7,8,9,10"; // // txtBatchWriteAddress // this.txtBatchWriteAddress.Location = new System.Drawing.Point(95, 23); this.txtBatchWriteAddress.Name = "txtBatchWriteAddress"; this.txtBatchWriteAddress.Size = new System.Drawing.Size(70, 21); this.txtBatchWriteAddress.TabIndex = 10; this.txtBatchWriteAddress.Text = "D100"; // // lblBatchWriteData // this.lblBatchWriteData.AutoSize = true; this.lblBatchWriteData.Location = new System.Drawing.Point(15, 54); this.lblBatchWriteData.Name = "lblBatchWriteData"; this.lblBatchWriteData.Size = new System.Drawing.Size(59, 12); this.lblBatchWriteData.TabIndex = 9; this.lblBatchWriteData.Text = "写入数据:"; // // lblBatchWriteAddress // this.lblBatchWriteAddress.AutoSize = true; this.lblBatchWriteAddress.Location = new System.Drawing.Point(15, 26); this.lblBatchWriteAddress.Name = "lblBatchWriteAddress"; this.lblBatchWriteAddress.Size = new System.Drawing.Size(59, 12); this.lblBatchWriteAddress.TabIndex = 8; this.lblBatchWriteAddress.Text = "写入地址:"; // // cmbBatchWriteDataType // this.cmbBatchWriteDataType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbBatchWriteDataType.FormattingEnabled = true; this.cmbBatchWriteDataType.Location = new System.Drawing.Point(95, 78); this.cmbBatchWriteDataType.Name = "cmbBatchWriteDataType"; this.cmbBatchWriteDataType.Size = new System.Drawing.Size(120, 20); this.cmbBatchWriteDataType.TabIndex = 7; // // lblBatchWriteDataType // this.lblBatchWriteDataType.AutoSize = true; this.lblBatchWriteDataType.Location = new System.Drawing.Point(15, 81); this.lblBatchWriteDataType.Name = "lblBatchWriteDataType"; this.lblBatchWriteDataType.Size = new System.Drawing.Size(59, 12); this.lblBatchWriteDataType.TabIndex = 6; this.lblBatchWriteDataType.Text = "数据类型:"; // // groupBox4 // this.groupBox4.Controls.Add(this.btnClearMultiResult); this.groupBox4.Controls.Add(this.lblMultiAddressResult); this.groupBox4.Controls.Add(this.txtMultiAddressResult); this.groupBox4.Controls.Add(this.btnMultiAddressRead); this.groupBox4.Controls.Add(this.txtMultiAddresses); this.groupBox4.Controls.Add(this.lblMultiAddresses); this.groupBox4.Location = new System.Drawing.Point(20, 323); this.groupBox4.Name = "groupBox4"; this.groupBox4.Size = new System.Drawing.Size(470, 185); this.groupBox4.TabIndex = 18; this.groupBox4.TabStop = false; this.groupBox4.Text = "多地址读取(多个独立通信)"; // // btnClearMultiResult // this.btnClearMultiResult.Location = new System.Drawing.Point(390, 51); this.btnClearMultiResult.Name = "btnClearMultiResult"; this.btnClearMultiResult.Size = new System.Drawing.Size(65, 23); this.btnClearMultiResult.TabIndex = 5; this.btnClearMultiResult.Text = "清空"; this.btnClearMultiResult.UseVisualStyleBackColor = true; this.btnClearMultiResult.Click += new System.EventHandler(this.btnClearMultiResult_Click); // // lblMultiAddressResult // this.lblMultiAddressResult.AutoSize = true; this.lblMultiAddressResult.Location = new System.Drawing.Point(15, 92); this.lblMultiAddressResult.Name = "lblMultiAddressResult"; this.lblMultiAddressResult.Size = new System.Drawing.Size(35, 12); this.lblMultiAddressResult.TabIndex = 4; this.lblMultiAddressResult.Text = "结果:"; // // txtMultiAddressResult // this.txtMultiAddressResult.Location = new System.Drawing.Point(15, 111); this.txtMultiAddressResult.Multiline = true; this.txtMultiAddressResult.Name = "txtMultiAddressResult"; this.txtMultiAddressResult.ReadOnly = true; this.txtMultiAddressResult.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.txtMultiAddressResult.Size = new System.Drawing.Size(440, 60); this.txtMultiAddressResult.TabIndex = 3; // // btnMultiAddressRead // this.btnMultiAddressRead.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(192))))); this.btnMultiAddressRead.Location = new System.Drawing.Point(300, 23); this.btnMultiAddressRead.Name = "btnMultiAddressRead"; this.btnMultiAddressRead.Size = new System.Drawing.Size(80, 28); this.btnMultiAddressRead.TabIndex = 2; this.btnMultiAddressRead.Text = "多地址读取"; this.btnMultiAddressRead.UseVisualStyleBackColor = false; this.btnMultiAddressRead.Click += new System.EventHandler(this.btnMultiAddressRead_Click); // // txtMultiAddresses // this.txtMultiAddresses.Location = new System.Drawing.Point(95, 23); this.txtMultiAddresses.Multiline = true; this.txtMultiAddresses.Name = "txtMultiAddresses"; this.txtMultiAddresses.Size = new System.Drawing.Size(190, 56); this.txtMultiAddresses.TabIndex = 1; this.txtMultiAddresses.Text = "D0,D10,D20,D30"; // // lblMultiAddresses // this.lblMultiAddresses.AutoSize = true; this.lblMultiAddresses.Location = new System.Drawing.Point(15, 26); this.lblMultiAddresses.Name = "lblMultiAddresses"; this.lblMultiAddresses.Size = new System.Drawing.Size(59, 12); this.lblMultiAddresses.TabIndex = 0; this.lblMultiAddresses.Text = "多个地址:"; // // groupBox5 // this.groupBox5.Controls.Add(this.lblMultiAddressWriteResult); this.groupBox5.Controls.Add(this.txtMultiAddressWriteResult); this.groupBox5.Controls.Add(this.btnMultiAddressWrite); this.groupBox5.Controls.Add(this.txtMultiAddressWriteData); this.groupBox5.Controls.Add(this.lblMultiAddressWriteData); this.groupBox5.Location = new System.Drawing.Point(500, 323); this.groupBox5.Name = "groupBox5"; this.groupBox5.Size = new System.Drawing.Size(470, 185); this.groupBox5.TabIndex = 19; this.groupBox5.TabStop = false; this.groupBox5.Text = "多地址写入(多个独立通信)"; // // lblMultiAddressWriteResult // this.lblMultiAddressWriteResult.AutoSize = true; this.lblMultiAddressWriteResult.Location = new System.Drawing.Point(15, 92); this.lblMultiAddressWriteResult.Name = "lblMultiAddressWriteResult"; this.lblMultiAddressWriteResult.Size = new System.Drawing.Size(35, 12); this.lblMultiAddressWriteResult.TabIndex = 4; this.lblMultiAddressWriteResult.Text = "结果:"; // // txtMultiAddressWriteResult // this.txtMultiAddressWriteResult.Location = new System.Drawing.Point(15, 111); this.txtMultiAddressWriteResult.Multiline = true; this.txtMultiAddressWriteResult.Name = "txtMultiAddressWriteResult"; this.txtMultiAddressWriteResult.ReadOnly = true; this.txtMultiAddressWriteResult.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.txtMultiAddressWriteResult.Size = new System.Drawing.Size(440, 60); this.txtMultiAddressWriteResult.TabIndex = 3; // // btnMultiAddressWrite // this.btnMultiAddressWrite.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(192))))); this.btnMultiAddressWrite.Location = new System.Drawing.Point(300, 23); this.btnMultiAddressWrite.Name = "btnMultiAddressWrite"; this.btnMultiAddressWrite.Size = new System.Drawing.Size(80, 28); this.btnMultiAddressWrite.TabIndex = 2; this.btnMultiAddressWrite.Text = "多地址写入"; this.btnMultiAddressWrite.UseVisualStyleBackColor = false; this.btnMultiAddressWrite.Click += new System.EventHandler(this.btnMultiAddressWrite_Click); // // txtMultiAddressWriteData // this.txtMultiAddressWriteData.Location = new System.Drawing.Point(95, 23); this.txtMultiAddressWriteData.Multiline = true; this.txtMultiAddressWriteData.Name = "txtMultiAddressWriteData"; this.txtMultiAddressWriteData.Size = new System.Drawing.Size(190, 56); this.txtMultiAddressWriteData.TabIndex = 1; this.txtMultiAddressWriteData.Text = "D0=100,D1=200,D2=300"; // // lblMultiAddressWriteData // this.lblMultiAddressWriteData.AutoSize = true; this.lblMultiAddressWriteData.Location = new System.Drawing.Point(15, 26); this.lblMultiAddressWriteData.Name = "lblMultiAddressWriteData"; this.lblMultiAddressWriteData.Size = new System.Drawing.Size(65, 12); this.lblMultiAddressWriteData.TabIndex = 0; this.lblMultiAddressWriteData.Text = "地址=数值:"; // // btnTestAll // this.btnTestAll.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(128))))); this.btnTestAll.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.btnTestAll.Location = new System.Drawing.Point(250, 18); this.btnTestAll.Name = "btnTestAll"; this.btnTestAll.Size = new System.Drawing.Size(120, 32); this.btnTestAll.TabIndex = 20; this.btnTestAll.Text = "测试批量功能"; this.btnTestAll.UseVisualStyleBackColor = false; this.btnTestAll.Click += new System.EventHandler(this.btnTestAll_Click); // // btnExampleReadBits // this.btnExampleReadBits.Location = new System.Drawing.Point(220, 85); this.btnExampleReadBits.Name = "btnExampleReadBits"; this.btnExampleReadBits.Size = new System.Drawing.Size(50, 25); this.btnExampleReadBits.TabIndex = 0; this.btnExampleReadBits.Text = "位元件"; this.btnExampleReadBits.Click += new System.EventHandler(this.btnExampleReadBits_Click); // // btnExampleWriteBits // this.btnExampleWriteBits.Location = new System.Drawing.Point(270, 85); this.btnExampleWriteBits.Name = "btnExampleWriteBits"; this.btnExampleWriteBits.Size = new System.Drawing.Size(65, 25); this.btnExampleWriteBits.TabIndex = 0; this.btnExampleWriteBits.Text = "位元件"; this.btnExampleWriteBits.Click += new System.EventHandler(this.btnExampleWriteBits_Click); // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(984, 518); this.Controls.Add(this.btnTestAll); this.Controls.Add(this.groupBox5); this.Controls.Add(this.groupBox4); this.Controls.Add(this.groupBox3); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); this.Controls.Add(this.lblConnectionStatus); this.Controls.Add(this.btnDisconnect); this.Controls.Add(this.btnConnect); this.MaximizeBox = false; this.MinimumSize = new System.Drawing.Size(1000, 557); this.Name = "Form1"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "CSharpFx5u - FX5U 通讯测试 (支持批量操作)"; this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); this.groupBox2.ResumeLayout(false); this.groupBox2.PerformLayout(); this.groupBox3.ResumeLayout(false); this.groupBox3.PerformLayout(); this.groupBox4.ResumeLayout(false); this.groupBox4.PerformLayout(); this.groupBox5.ResumeLayout(false); this.groupBox5.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Button btnConnect; private System.Windows.Forms.Button btnDisconnect; private System.Windows.Forms.TextBox txtAddress; private System.Windows.Forms.TextBox txtValue; private System.Windows.Forms.Button btnReadBool; private System.Windows.Forms.Button btnWriteBool; private System.Windows.Forms.Button btnReadInt; private System.Windows.Forms.Button btnWriteInt; private System.Windows.Forms.Button btnReadFloat; private System.Windows.Forms.Button btnWriteFloat; private System.Windows.Forms.Button btnReadDouble; private System.Windows.Forms.Button btnWriteDouble; private System.Windows.Forms.Label lblAddr; private System.Windows.Forms.Label lblValue; private System.Windows.Forms.Label lblConnectionStatus; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.TextBox txtBatchStartAddress; private System.Windows.Forms.TextBox txtBatchCount; private System.Windows.Forms.Button btnBatchRead; private System.Windows.Forms.Label lblBatchStartAddress; private System.Windows.Forms.Label lblBatchCount; private System.Windows.Forms.TextBox txtBatchResult; private System.Windows.Forms.Label lblBatchResult; private System.Windows.Forms.Button btnClearBatchResult; private System.Windows.Forms.Button btnExampleRead10; private System.Windows.Forms.GroupBox groupBox3; private System.Windows.Forms.Label lblBatchWriteResult; private System.Windows.Forms.Button btnBatchWrite; private System.Windows.Forms.TextBox txtBatchWriteData; private System.Windows.Forms.TextBox txtBatchWriteAddress; private System.Windows.Forms.Label lblBatchWriteData; private System.Windows.Forms.Label lblBatchWriteAddress; private System.Windows.Forms.GroupBox groupBox4; private System.Windows.Forms.Button btnClearMultiResult; private System.Windows.Forms.Label lblMultiAddressResult; private System.Windows.Forms.TextBox txtMultiAddressResult; private System.Windows.Forms.Button btnMultiAddressRead; private System.Windows.Forms.TextBox txtMultiAddresses; private System.Windows.Forms.Label lblMultiAddresses; private System.Windows.Forms.GroupBox groupBox5; private System.Windows.Forms.Label lblMultiAddressWriteResult; private System.Windows.Forms.TextBox txtMultiAddressWriteResult; private System.Windows.Forms.Button btnMultiAddressWrite; private System.Windows.Forms.TextBox txtMultiAddressWriteData; private System.Windows.Forms.Label lblMultiAddressWriteData; private System.Windows.Forms.Button btnTestAll; private System.Windows.Forms.ComboBox cmbBatchDataType; private System.Windows.Forms.Label lblBatchDataType; private System.Windows.Forms.ComboBox cmbBatchWriteDataType; private System.Windows.Forms.Label lblBatchWriteDataType; private System.Windows.Forms.Button btnExampleReadFloat; private System.Windows.Forms.Button btnExampleWriteFloat; private System.Windows.Forms.Button btnExampleWrite10; private System.Windows.Forms.Button btnBatchReadHelp; private System.Windows.Forms.Button btnBatchWriteHelp; // 在控件声明部分添加: private System.Windows.Forms.Button btnExampleReadBits; private System.Windows.Forms.Button btnExampleWriteBits; } }Program.cs
using System; using System.Windows.Forms; namespace CSharpFx5u { internal static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } }如果使用起来麻烦也可以直接下载资源~ 本程序仅测试了bool、int16、float、double数据类型的测试,如果还有其他需要测试的请自行丢入ai修改~