using System;
using System.Collections.Generic;
using System.Drawing;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
namespace MELSEC_FX3U_Comm
{
public partial class MainForm : Form
{
private TcpClient plcClient;
private NetworkStream stream;
private Timer refreshTimer;
private byte station = 0x00;
// PLC寄存器状态存储
private bool[] xStatus = new bool[8];
private bool[] yStatus = new bool[8];
private bool[] mStatus = new bool[10];
public MainForm()
{
InitializeComponent();
InitializePLCConnection();
SetupUI();
StartRefreshTimer();
}
private void InitializePLCConnection()
{
try
{
plcClient = new TcpClient();
plcClient.Connect(IPAddress.Parse("192.168.0.250"), 5551);
stream = plcClient.GetStream();
StatusLabel.Text = "已连接到PLC";
}
catch (Exception ex)
{
StatusLabel.Text = $"连接失败: {ex.Message}";
}
}
private void SetupUI()
{
// 初始化输入显示区域
for (int i = 0; i < 8; i++)
{
var cb = new CheckBox
{
Text = $"X{i}",
Location = new Point(20 + (i % 4) * 80, 20 + (i / 4) * 30),
AutoSize = true
};
xCheckBoxes.Add(cb);
this.Controls.Add(cb);
}
// 初始化输出显示区域
for (int i = 0; i < 8; i++)
{
var cb = new CheckBox
{
Text = $"Y{i}",
Location = new Point(200 + (i % 4) * 80, 20 + (i / 4) * 30),
AutoSize = true
};
yCheckBoxes.Add(cb);
this.Controls.Add(cb);
}
// 初始化M寄存器按钮
for (int i = 0; i < 10; i++)
{
var btn = new Button
{
Text = $"M{i}",
Location = new Point(380 + (i % 5) * 80, 20 + (i / 5) * 30),
Width = 70
};
btn.Click += (s, e) => ToggleMRegister(i);
mButtons.Add(btn);
this.Controls.Add(btn);
}
}
private void StartRefreshTimer()
{
refreshTimer = new Timer { Interval = 500 };
refreshTimer.Tick += async (s, e) => await ReadPLCData();
refreshTimer.Start();
}
private async Task ReadPLCData()
{
try
{
// 读取X寄存器
byte[] xData = ReadRegisters(0x0000, 8);
for (int i = 0; i < 8; i++)
xStatus = (xData[i / 8] & (1 << (7 - (i % 8)))) != 0;
// 读取Y寄存器
byte[] yData = ReadRegisters(0x0010, 8);
for (int i = 0; i < 8; i++)
yStatus = (yData[i / 8] & (1 << (7 - (i % 8)))) != 0;
UpdateUI();
}
catch (Exception ex)
{
StatusLabel.Text = $"读取错误: {ex.Message}";
}
}
private byte[] ReadRegisters(ushort start, ushort length)
{
// 构建读取请求报文
List<byte> query = new List<byte>
{
0x80, 0x00, 0x00, 0x00, // 起始符
0x00, 0x02, // 控制代码
(byte)(station), 0x00, 0x00, // 站号、保留
(byte)(start >> 8), (byte)start, // 起始地址
(byte)(length >> 8), (byte)length,// 寄存器数量
0x00, 0x00 // 结束符
};
SendCommand(query.ToArray());
return ReadResponse();
}
private void ToggleMRegister(int index)
{
mStatus[index] = !mStatus[index];
WriteRegister(0x2000 + index, mStatus[index] ? 1 : 0);
mButtons[index].BackColor = mStatus[index] ? Color.LightGreen : SystemColors.Control;
}
private void WriteRegister(ushort address, ushort value)
{
// 构建写请求报文
List<byte> query = new List<byte>
{
0x80, 0x00, 0x00, 0x00, // 起始符
0x00, 0x12, // 控制代码
(byte)(station), 0x00, 0x00, // 站号、保留
(byte)(address >> 8), (byte)address,// 地址
(byte)(value >> 8), (byte)value, // 值
0x00, 0x00 // 结束符
};
SendCommand(query.ToArray());
}
private void SendCommand(byte[] command)
{
stream.Write(command, 0, command.Length);
}
private byte[] ReadResponse()
{
byte[] buffer = new byte[1024];
int bytesRead = stream.Read(buffer, 0, buffer.Length);
Array.Resize(ref buffer, bytesRead);
return buffer;
}
private void UpdateUI()
{
// 更新X寄存器显示
for (int i = 0; i < 8; i++)
xCheckBoxes.Checked = xStatus;
// 更新Y寄存器显示
for (int i = 0; i < 8; i++)
yCheckBoxes.Checked = yStatus;
// 更新M寄存器显示
for (int i = 0; i < 10; i++)
mButtons.BackColor = mStatus ? Color.LightGreen : SystemColors.Control;
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
plcClient?.Close();
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}