C#串口通信与动态曲线绘制实现

一、系统概述

基于C# WinForms实现串口通信与动态曲线绘制,核心功能包括:

  1. 串口配置与连接:支持选择串口号、波特率等参数,连接/断开硬件设备;

  2. 数据接收与解析:异步接收硬件发送的串口数据(支持ASCII/二进制格式),解析为数值型数据点;

  3. 动态曲线绘制:使用Chart控件实时显示数据变化趋势,支持自动滚动、缩放、数据点标记;

  4. 异常处理:串口通信错误、数据解析失败的容错机制。

应用场景:传感器数据采集(如温度、压力)、仪器监控、工业设备数据可视化等。

二、核心组件与技术选型

模块 技术方案 说明
串口通信 System.IO.Ports.SerialPort C#内置串口类,支持异步接收(DataReceived事件)
数据解析 字符串分割/二进制转换(BitConverter 按硬件协议解析数据(如CSV格式、自定义帧)
曲线绘制 System.Windows.Forms.DataVisualization.Charting.Chart WinForms图表控件,支持动态更新、多曲线显示
UI框架 WinForms(.NET Framework 4.8) 简单易用,适合快速开发桌面应用

三、实现步骤与代码

3.1 界面设计(WinForms)

添加以下控件(命名为MainForm):

  • 串口配置区ComboBox(串口号)、ComboBox(波特率,预设9600/115200等)、Button(连接/断开);

  • 数据显示区TextBox(多行,显示原始数据,只读)、Chart(命名为chartData,显示动态曲线);

  • 状态栏Label(显示连接状态)。

3.2 串口通信模块(核心代码)

3.2.1 串口初始化与连接

using System.IO.Ports;
using System.Windows.Forms;

public partial class MainForm : Form
{
    private SerialPort serialPort = new SerialPort();
    private bool isConnected = false;

    // 初始化串口参数
    private void InitSerialPort()
    {
        // 获取可用串口号
        comboBoxPort.Items.AddRange(SerialPort.GetPortNames());
        if (comboBoxPort.Items.Count > 0) comboBoxPort.SelectedIndex = 0;

        // 预设波特率
        comboBoxBaudRate.Items.AddRange(new object[] { "9600", "19200", "38400", "57600", "115200" });
        comboBoxBaudRate.SelectedIndex = 4; // 默认115200

        // 串口参数配置
        serialPort.DataReceived += SerialPort_DataReceived; // 异步接收事件
        serialPort.ReadTimeout = 500;
        serialPort.WriteTimeout = 500;
    }

    // 连接/断开串口
    private void btnConnect_Click(object sender, EventArgs e)
    {
        if (!isConnected)
        {
            try
            {
                serialPort.PortName = comboBoxPort.Text;
                serialPort.BaudRate = int.Parse(comboBoxBaudRate.Text);
                serialPort.DataBits = 8;
                serialPort.StopBits = StopBits.One;
                serialPort.Parity = Parity.None;
                serialPort.Open();
                isConnected = true;
                btnConnect.Text = "断开连接";
                lblStatus.Text = $"已连接:{serialPort.PortName}@{serialPort.BaudRate}bps";
            }
            catch (Exception ex)
            {
                MessageBox.Show($"连接失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        else
        {
            serialPort.Close();
            isConnected = false;
            btnConnect.Text = "连接";
            lblStatus.Text = "未连接";
        }
    }
}

3.2.2 异步接收与数据解析

假设硬件发送ASCII格式数据,每行一个浮点数(如温度值),以\n结尾:

// 串口数据接收事件(异步)
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    if (!serialPort.IsOpen) return;

    try
    {
        string rawData = serialPort.ReadExisting(); // 读取所有可用数据
        this.Invoke((MethodInvoker)delegate {
            // 显示原始数据
            txtRawData.AppendText(rawData);
            
            // 解析数据(按行分割,过滤空行)
            string[] lines = rawData.Split('\n');
            foreach (string line in lines)
            {
                if (string.IsNullOrWhiteSpace(line)) continue;
                if (float.TryParse(line.Trim(), out float value))
                {
                    // 解析成功,添加到曲线数据
                    AddDataPoint(value);
                }
                else
                {
                    txtRawData.AppendText($"【解析失败】{line}\r\n");
                }
            }
        });
    }
    catch (Exception ex)
    {
        this.Invoke((MethodInvoker)delegate {
            txtRawData.AppendText($"【接收错误】{ex.Message}\r\n");
        });
    }
}

3.3 动态曲线绘制模块(Chart控件)

3.3.1 初始化图表

using System.Windows.Forms.DataVisualization.Charting;

private Series series; // 曲线数据系列
private int maxPoints = 100; // 最大显示点数(超过则滚动)

private void InitChart()
{
    // 设置图表区域
    chartData.ChartAreas.Clear();
    ChartArea chartArea = new ChartArea("MainArea");
    chartArea.AxisX.Title = "时间(点)";
    chartArea.AxisY.Title = "数值";
    chartArea.AxisX.ScaleView.Zoomable = true; // 允许缩放
    chartArea.CursorX.IsUserEnabled = true;
    chartArea.CursorX.IsUserSelectionEnabled = true;
    chartData.ChartAreas.Add(chartArea);

    // 添加数据系列(折线图)
    series = new Series("数据曲线");
    series.ChartType = SeriesChartType.Line;
    series.Color = Color.Blue;
    series.BorderWidth = 2;
    series.XValueType = ChartValueType.Int32;
    series.YValueType = ChartValueType.Single;
    chartData.Series.Add(series);
}

3.3.2 动态添加数据点

private int pointCount = 0; // 当前点数

// 添加新数据点到曲线
private void AddDataPoint(float value)
{
    pointCount++;
    series.Points.AddXY(pointCount, value);

    // 超过最大点数时,移除最早的点(保持滚动效果)
    if (series.Points.Count > maxPoints)
    {
        series.Points.RemoveAt(0);
    }

    // 自动调整X轴范围(显示最新点)
    chartData.ChartAreas[0].AxisX.Minimum = Math.Max(1, pointCount - maxPoints + 1);
    chartData.ChartAreas[0].AxisX.Maximum = pointCount;

    // 刷新图表(避免频繁刷新可加定时器节流)
    chartData.Invalidate();
}

3.4 完整主窗体代码(整合模块)

using System;
using System.IO.Ports;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace SerialPortCurveDisplay
{
    public partial class MainForm : Form
    {
        private SerialPort serialPort = new SerialPort();
        private bool isConnected = false;
        private Series series;
        private int maxPoints = 100;
        private int pointCount = 0;

        public MainForm()
        {
            InitializeComponent();
            InitSerialPort(); // 初始化串口配置
            InitChart();      // 初始化图表
        }

        // 【省略InitSerialPort、InitChart、btnConnect_Click、SerialPort_DataReceived、AddDataPoint方法,见上文】

        #region UI控件事件
        private void MainForm_Load(object sender, EventArgs e)
        {
            lblStatus.Text = "未连接";
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (isConnected) serialPort.Close();
        }
        #endregion
    }
}

参考代码 C#通过串口连接硬件设备,并获取硬件数据,然后将数据点绘制成动态曲线,显示出来! www.youwenfan.com/contentcnt/182233.html

四、扩展功能

  1. 多曲线显示:添加多个Series,支持同时显示多路传感器数据(如温度、湿度);

  2. 数据存储:将解析后的数据保存到CSV文件(用StreamWriter);

  3. 参数配置:允许用户设置曲线颜色、线宽、最大点数等;

  4. 报警功能:设置阈值,数据超限时弹窗或闪烁提示。

posted @ 2026-04-06 13:58  w199899899  阅读(57)  评论(0)    收藏  举报