基于C# WinForm实现串口数据读取与实时折线图显示

📅 发布时间:2026/7/6 10:57:03 👁️ 浏览次数:
基于C# WinForm实现串口数据读取与实时折线图显示
一、系统架构设计RS232/USB串口设备串口通信模块数据解析器实时数据缓冲区Chart控件更新用户界面二、核心代码实现1. 串口通信模块SerialPortManager.csusingSystem.IO.Ports;usingSystem.Threading.Tasks;publicclassSerialPortManager:IDisposable{privateSerialPort_port;privatereadonlyBlockingCollectionbyte[]_buffernew(100);privateCancellationTokenSource_cts;publiceventActionbyte[]DataReceived;publicvoidConnect(stringportName,intbaudRate115200){_portnewSerialPort(portName,baudRate,Parity.None,8,StopBits.One){ReadTimeout1000,WriteTimeout1000};_ctsnewCancellationTokenSource();_Task.Run(()ReadDataAsync(_cts.Token));}privateasyncTaskReadDataAsync(CancellationTokentoken){try{while(!token.IsCancellationRequested){intbytesAvailable_port.BytesToRead;if(bytesAvailable0){byte[]chunknewbyte[bytesAvailable];_port.Read(chunk,0,bytesAvailable);_buffer.Add(chunk,token);DataReceived?.Invoke(chunk);}awaitTask.Delay(10,token);}}catch(OperationCanceledException){}catch(Exceptionex){HandleError($串口读取错误:{ex.Message});}}publicvoidDisconnect()_port?.Close();publicvoidDispose()_port?.Dispose();privatevoidHandleError(stringmessage){// 实现错误处理逻辑}}2. 数据解析与图表更新MainForm.csusingSystem.Windows.Forms.DataVisualization.Charting;publicpartialclassMainForm:Form{privatereadonlySerialPortManager_serialManager;privatereadonlyCircularBufferfloat_dataBuffernew(1000);privateChart_chart;privateSeries_series;publicMainForm(){InitializeComponent();InitializeChart();_serialManagernewSerialPortManager();_serialManager.DataReceivedOnDataReceived;}privatevoidInitializeChart(){_chartnewChart{DockDockStyle.Fill};_seriesnewSeries(传感器数据){ChartTypeSeriesChartType.Spline,BorderWidth2,ColorColor.Blue};_chart.Series.Add(_series);_chart.ChartAreas[0].AxisX.Title时间;_chart.ChartAreas[0].AxisY.Title数值;_chart.ChartAreas[0].AxisX.Interval1;_chart.ChartAreas[0].AxisY.Interval5;this.Controls.Add(_chart);}privatevoidOnDataReceived(byte[]data){if(InvokeRequired){Invoke(newAction(()OnDataReceived(data)));return;}// 假设数据格式温度高字节温度低字节16位if(data.Length2){shortraw(short)(data[0]8|data[1]);floatvalueraw/10.0f;_dataBuffer.Enqueue(value);UpdateChart();}}privatevoidUpdateChart(){if(_dataBuffer.Count_chart.Series[0].Points.Count){_chart.Series[0].Points.AddY(_dataBuffer.Last());if(_chart.Series[0].Points.Count1000){_chart.Series[0].Points.RemoveAt(0);}}// 启用双缓冲减少闪烁_chart.DoubleBufferedtrue;_chart.Invalidate();}privatevoidbtnConnect_Click(objectsender,EventArgse){_serialManager.Connect(COM3);}privatevoidbtnDisconnect_Click(objectsender,EventArgse){_serialManager.Disconnect();}}三、关键功能实现1. 数据缓冲区CircularBuffer.cspublicclassCircularBufferT{privatereadonlyT[]_buffer;privateint_head;privateint_tail;privateint_count;publicCircularBuffer(intcapacity){_buffernewT[capacity];}publicvoidEnqueue(Titem){_buffer[_head]item;_head(_head1)%_buffer.Length;if(_count_buffer.Length)_count;else_tail(_tail1)%_buffer.Length;}publicTDequeue()_buffer[_tail];publicTLast()_buffer[(_tail_count-1)%_buffer.Length];publicintCount_count;}2. 性能优化配置// 在Form_Load事件中配置privatevoidMainForm_Load(objectsender,EventArgse){// 启用双缓冲this.DoubleBufferedtrue;// 设置控件更新模式_chart.Series[0].ChartTypeSeriesChartType.FastLine;_chart.ChartAreas[0].AxisX.ScrollBar.Enabledtrue;_chart.ChartAreas[0].AxisX.ScaleView.Size60;// 显示最近60秒数据}// 定时清理旧数据privatevoidtimerCleanup_Tick(objectsender,EventArgse){while(_dataBuffer.Count1000){_dataBuffer.Dequeue();_chart.Series[0].Points.RemoveAt(0);}}四、界面设计MainForm.Designer.cspartialclassMainForm{privateSystem.ComponentModel.IContainercomponentsnull;privateButtonbtnConnect;privateButtonbtnDisconnect;protectedoverridevoidDispose(booldisposing){if(disposing(components!null)){components.Dispose();}base.Dispose(disposing);}privatevoidInitializeComponent(){this.btnConnectnewSystem.Windows.Forms.Button();this.btnDisconnectnewSystem.Windows.Forms.Button();this.SuspendLayout();// 连接按钮this.btnConnect.LocationnewSystem.Drawing.Point(20,20);this.btnConnect.SizenewSystem.Drawing.Size(75,23);this.btnConnect.Text连接;this.btnConnect.ClicknewSystem.EventHandler(this.btnConnect_Click);// 断开按钮this.btnDisconnect.LocationnewSystem.Drawing.Point(101,20);this.btnDisconnect.SizenewSystem.Drawing.Size(75,23);this.btnDisconnect.Text断开;this.btnDisconnect.ClicknewSystem.EventHandler(this.btnDisconnect_Click);// 主布局this.Controls.Add(this.btnDisconnect);this.Controls.Add(this.btnConnect);this.ClientSizenewSystem.Drawing.Size(800,600);this.NameMainForm;this.Text串口实时监控;this.ResumeLayout(false);}}五、扩展功能实现1. 多通道支持// 修改数据解析逻辑privatevoidOnDataReceived(byte[]data){if(data.Length4){shorttempRaw(short)(data[0]8|data[1]);shorthumiRaw(short)(data[2]8|data[3]);floattemptempRaw/10.0f;floathumihumiRaw/10.0f;_tempBuffer.Enqueue(temp);_humiBuffer.Enqueue(humi);UpdateCharts();}}privatevoidUpdateCharts(){if(_chart.Series.Count2){_chart.Series.Add(newSeries(湿度){ChartTypeSeriesChartType.Spline,ColorColor.Red});}// 更新温度曲线if(_tempBuffer.Count_chart.Series[0].Points.Count){_chart.Series[0].Points.AddY(_tempBuffer.Last());_chart.Series[0].Points.RemoveAt(0);}// 更新湿度曲线if(_humiBuffer.Count_chart.Series[1].Points.Count){_chart.Series[1].Points.AddY(_humiBuffer.Last());_chart.Series[1].Points.RemoveAt(0);}}2. 数据存储集成// 添加SQLite存储publicclassDataStorage{privatereadonlystring_dbPathdata.sqlite;publicvoidSaveData(floattemp,floathumi){using(varconnnewSQLiteConnection($Data Source{_dbPath};Version3;)){conn.Open();varcmdnewSQLiteCommand(INSERT INTO sensor_data (timestamp, temperature, humidity) VALUES (datetime(now), temp, humi),conn);cmd.Parameters.AddWithValue(temp,temp);cmd.Parameters.AddWithValue(humi,humi);cmd.ExecuteNonQuery();}}}// 在OnDataReceived中调用privatevoidOnDataReceived(byte[]data){// ...解析数据..._storage.SaveData(temp,humi);}六、调试与优化建议1. 性能监控// 在状态栏显示性能指标privatevoidUpdatePerformanceMetrics(){varcpuUsagenewPerformanceCounter(Processor,% Processor Time,_Total);varramUsagenewPerformanceCounter(Memory,Available MBytes);lblStatus.Text$CPU:{cpuUsage.NextValue()}% | 内存:{ramUsage.NextValue()}MB;}2. 异常处理// 添加串口状态监控privatevoidCheckSerialPortStatus(){if(!_serialManager.IsOpen){btnConnect.Enabledtrue;btnDisconnect.Enabledfalse;lblStatus.Text串口未连接;}else{btnConnect.Enabledfalse;btnDisconnect.Enabledtrue;lblStatus.Text数据接收中...;}}七、部署方案1. 安装包配置Inno Setup脚本[Files] Source: YourApp.exe; DestDir: {app}; Flags: ignoreversion Source: zlgcan.dll; DestDir: {app}; Flags: ignoreversion Source: data.sqlite; DestDir: {app}; Flags: ignoreversion [Icons] Name: {group}\实时监控; Filename: {app}\YourApp.exe2. 系统服务化publicclassBackgroundService:ServiceBase{protectedoverridevoidOnStart(string[]args){_serialManager.Connect(COM3);_timer.Start();}protectedoverridevoidOnStop(){_serialManager.Disconnect();_timer.Stop();}}参考代码 使用C#的winform读取串口并用chart控件显示实时数据折线图www.youwenfan.com/contentcsr/112224.html八、测试用例1. 模拟数据测试// 生成测试数据privatevoidGenerateTestData(){varrandnewRandom();vartimernewTimer(100);timer.Elapsed(s,e){vartemp20rand.NextDouble()*10;varhumi40rand.NextDouble()*20;_serialManager.RaiseDataReceived(newbyte[]{(byte)(temp8),(byte)temp,(byte)(humi8),(byte)humi});};timer.Start();}2. 压力测试// 高负载数据测试privatevoidHighLoadTest(){varbuffernewbyte[1024*1024];// 1MB数据块Parallel.For(0,1000,i{_serialManager.RaiseDataReceived(buffer);});}