【ModBus 485 四通道设备C#上位机设计】
1. 概述
源码地址:【ModBus 485 四通道设备C#上位机设计】
在现代工业自动化中,ModBus 协议是一种广泛使用的通信协议,尤其是在 RS485 网络中。本文将介绍如何使用 C# 开发一个基于 ModBus RTU 协议的上位机软件,用于与四通道设备(如RS485超声波风速风向传感器)进行通信,并实时显示风速、风向等数据。
2. 开发环境
- 开发工具:Visual Studio 2022,环境搭建参考博客:【VS2019安装+QT配置】
- 编程语言:C#
- 通信协议:ModBus RTU
- 硬件接口:
2. 【高效12v开关电源】
3. 🎁【USB转485/422转换器】
多模式适应,灵活切换场景!!,高速串口,智能双向传输,稳定高效!!,一键跳线,自动识别信号,简化操作!!
技术强者优选
3. 功能需求
- 串口通信:支持串口的打开、关闭、配置(波特率、数据位、校验位、停止位)。
- 数据解析:解析 ModBus RTU 协议数据,获取风速、风向、最大风速、风力等级等信息。
- 实时显示:
- 实时风速和最大风速以折线图形式显示。
- 当前风向以圆盘指针形式显示。
- 日志记录:将接收到的数据记录到日志文件中。
- 定时读取:支持定时读取传感器数据。
4. 实现步骤
From界面设计
完整Form1.cs
程序
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Threading;
using System.Windows.Forms;
namespace Modbus_RTU
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitializePortSelection(); // 初始化串口端口选择
InitializeChart(); // 初始化图表
}
/// <summary>
/// 初始化串口配置
/// </summary>
private void InitializePortSelection()
{
serialPort.PortName = cboPortName.Text;
serialPort.BaudRate = int.Parse(cboBaudRate.Text);
serialPort.DataBits = int.Parse(cboData.Text);
serialPort.Parity = (Parity)Enum.Parse(typeof(Parity), cboTest.Text);
serialPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cboStop.Text);
}
/// <summary>
/// 初始化图表
/// </summary>
private void InitializeChart()
{
// 清除默认的 Series
chartWindSpeed.Series.Clear();
// 设置图表区域
chartWindSpeed.ChartAreas.Clear();
var chartArea = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
chartWindSpeed.ChartAreas.Add(chartArea);
// 添加实时风速序列
var seriesRealTime = new System.Windows.Forms.DataVisualization.Charting.Series
{
Name = "RealTimeWindSpeed",
Color = Color.Blue,
ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line,
BorderWidth = 2, // 设置线条宽度
};
chartWindSpeed.Series.Add(seriesRealTime);
// 添加最大风速序列
var seriesMax = new System.Windows.Forms.DataVisualization.Charting.Series
{
Name = "MaxWindSpeed",
Color = Color.Red,
ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line,
BorderWidth = 2, // 设置线条宽度
};
chartWindSpeed.Series.Add(seriesMax);
// 设置X轴和Y轴标题
chartArea.AxisX.Title = "时间";
chartArea.AxisY.Title = "风速 (m/s)";
// 设置平滑曲线
chartArea.AxisX.IsMarginVisible = false;
chartArea.AxisY.IsMarginVisible = false;
// 设置X轴和Y轴范围
chartArea.AxisX.Minimum = 0;
chartArea.AxisX.Maximum = 30;
chartWindSpeed.Update();
}
/// <summary>
/// 记录传感器数据日志
/// </summary>
/// <param name="windSpeed">风速</param>
/// <param name="windDirection">风向</param>
/// <param name="maxWindSpeed">最大风速</param>
/// <param name="windLevel">风力等级</param>
private void LogData(float windSpeed, int windDirection, float maxWindSpeed, int windLevel)
{
string logEntry = $"{
DateTime.Now:yyyy-MM-dd HH:mm:ss} - 风速: {
windSpeed:F2} m/s, 风向: {
windDirection}°, 最大风速: {
maxWindSpeed:F2} m/s, 风力等级: {
windLevel} 级\r\n";
File.AppendAllText("sensor_log.txt", logEntry);
}
/// <summary>
/// 扫描可用串口
/// </summary>
private void btnScan_Click(object sender, EventArgs e)
{
string[] portNames = SerialPort.GetPortNames();
cboPortName.Items.Clear();
cboPortName.Items.AddRange(portNames);
if (portNames.Length > 0)
cboPortName.Text = portNames[0];
}
/// <summary>
/// 打开或关闭串口
/// </summary>
private void btnOpenPort_Click(object sender, EventArgs e)
{
if (serialPort.IsOpen)
{
serialPort.Close();
btnOpenPort.Text = "打开串口";
panel2.BackColor = Color.Red;
}
else
{
InitializePortSelection();
try
{
serialPort.Open();
btnOpenPort.Text = "关闭串口";
panel2.BackColor = Color.Green;
MessageBox.Show("串口初始化成功!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
/// <summary>
/// 清除接收数据区域
/// </summary>
private void btnClearRec_Click(object sender, EventArgs e)
{
txtReceive.Text = string.Empty;
}
/// <summary>
/// 手动发送数据
/// </summary>
private