C#实现基于Modbus和TCP/IP协议的图表数据实时采集与展示
C#柱状图、折线图、饼图源码 可基于modbus,tcpip协议实时采集数据

在很多工业监控和数据分析场景中,我们需要实时采集数据并通过图表直观展示。今天咱们就来聊聊如何用C#结合Modbus和TCP/IP协议实现数据采集,并绘制柱状图、折线图和饼图。
基于Modbus和TCP/IP的数据采集
Modbus协议相关引用
首先,我们要引用Modbus.Device命名空间来操作Modbus设备。如果还没安装相关库,可以通过NuGet包管理器搜索Modbus.Device进行安装。
简单的TCP/IP连接代码示例
using System;
using System.Net.Sockets;
class TcpIpConnection
{
private TcpClient client;
private NetworkStream stream;
public TcpIpConnection(string ip, int port)
{
client = new TcpClient();
try
{
client.Connect(ip, port);
stream = client.GetStream();
}
catch (SocketException e)
{
Console.WriteLine($"连接失败: {e.Message}");
}
}
public void SendData(byte[] data)
{
if (stream.CanWrite)
{
stream.Write(data, 0, data.Length);
}
}
public byte[] ReceiveData(int bufferSize)
{
byte[] buffer = new byte[bufferSize];
int bytesRead = stream.Read(buffer, 0, buffer.Length);
byte[] receivedData = new byte[bytesRead];
Array.Copy(buffer, receivedData, bytesRead);
return receivedData;
}
public void Close()
{
stream.Close();
client.Close();
}
}
在这段代码里,TcpIpConnection类封装了TCP/IP连接的操作。构造函数尝试连接到指定的IP和端口,SendData方法用于发送数据,ReceiveData接收数据并返回,Close方法关闭连接。
Modbus数据读取示例
using Modbus.Device;
using System.Net.Sockets;
class ModbusDataReader
{
private TcpClient client;
private ModbusIpMaster master;
public ModbusDataReader(string ip, int port)
{
client = new TcpClient(ip, port);
master = ModbusIpMaster.CreateIp(client);
}
public ushort[] ReadHoldingRegisters(int slaveAddress, int startAddress, int numRegisters)
{
try
{
return master.ReadHoldingRegisters(slaveAddress, startAddress, numRegisters);
}
catch (Exception e)
{
Console.WriteLine($"读取寄存器错误: {e.Message}");
return null;
}
}
public void Dispose()
{
master.Dispose();
client.Close();
}
}
这里ModbusDataReader类使用ModbusIpMaster来读取Modbus设备的保持寄存器。构造函数创建连接,ReadHoldingRegisters方法实际执行读取操作,Dispose方法释放资源。
图表绘制
柱状图绘制
我们可以使用System.Windows.Forms.DataVisualization.Charting命名空间来绘制图表。先在项目中添加对System.Windows.Forms.DataVisualization的引用。
using System.Windows.Forms.DataVisualization.Charting;
class BarChartCreator
{
public static void CreateBarChart(Chart chart, string[] categories, int[] values)
{
chart.Series.Clear();
Series series = new Series("BarSeries");
series.ChartType = SeriesChartType.Column;
for (int i = 0; i < categories.Length; i++)
{
series.Points.AddXY(categories[i], values[i]);
}
chart.Series.Add(series);
}
}
在CreateBarChart方法里,先清空图表原有的序列,创建一个新的柱状图序列,然后根据传入的类别和对应的值添加数据点。
折线图绘制
class LineChartCreator
{
public static void CreateLineChart(Chart chart, string[] categories, int[] values)
{
chart.Series.Clear();
Series series = new Series("LineSeries");
series.ChartType = SeriesChartType.Line;
for (int i = 0; i < categories.Length; i++)
{
series.Points.AddXY(categories[i], values[i]);
}
chart.Series.Add(series);
}
}
折线图绘制和柱状图类似,只是把图表类型设置为SeriesChartType.Line。
饼图绘制
class PieChartCreator
{
public static void CreatePieChart(Chart chart, string[] labels, int[] values)
{
chart.Series.Clear();
Series series = new Series("PieSeries");
series.ChartType = SeriesChartType.Pie;
for (int i = 0; i < labels.Length; i++)
{
series.Points.AddXY(labels[i], values[i]);
}
chart.Series.Add(series);
}
}
饼图绘制也是类似的逻辑,图表类型设为SeriesChartType.Pie。
结合数据采集与图表更新
在实际应用中,我们可以定时采集数据并更新图表。
using System;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
public partial class MainForm : Form
{
private Timer dataUpdateTimer;
private ModbusDataReader reader;
public MainForm()
{
InitializeComponent();
dataUpdateTimer = new Timer();
dataUpdateTimer.Interval = 5000; // 每5秒更新一次
dataUpdateTimer.Tick += DataUpdateTimer_Tick;
reader = new ModbusDataReader("192.168.1.100", 502);
dataUpdateTimer.Start();
}
private void DataUpdateTimer_Tick(object sender, EventArgs e)
{
ushort[] registers = reader.ReadHoldingRegisters(1, 0, 5);
if (registers!= null)
{
int[] values = Array.ConvertAll(registers, Convert.ToInt32);
string[] categories = { "Cat1", "Cat2", "Cat3", "Cat4", "Cat5" };
BarChartCreator.CreateBarChart(barChart, categories, values);
LineChartCreator.CreateLineChart(lineChart, categories, values);
PieChartCreator.CreatePieChart(pieChart, categories, values);
}
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
reader.Dispose();
dataUpdateTimer.Stop();
}
}
在这个MainForm类里,我们创建了一个定时器,每5秒触发一次数据采集并更新柱状图、折线图和饼图。在FormClosing事件里释放资源并停止定时器。

通过上述步骤,我们就可以实现基于Modbus和TCP/IP协议的数据实时采集,并通过不同类型的图表进行直观展示啦。当然,实际应用中还可能需要更多的错误处理和优化,但这已经搭建起了一个基本的框架。希望对大家有所帮助!

更多推荐


所有评论(0)