前端时间做的串口示波器做了许多优化,其代码量也到达了将近2000行
在原本的基础上做了很多内容的增加,私信回复《串口助手》即可获取发布链接(还有很多内容尚未完善),欢迎朋友们提出改进意见以及点赞分享。 包括但不限于:
控件提示: 将鼠标悬停于控件上可以提示相关控件信息。
接收设置优化: 利用定时器更新UI控件防止当串口收发速度过快的时候导致UI进程被占用无法使用。
串口详细信息显示: 显示串口的详细信息包括蓝牙,CH340等详细内容的显示,方便我们在连接蓝牙设备,CH340设备的多串口选择。
热拔插刷新: 在使用串口的过程中拔插串口或者在软件启动后加入新的串口时会刷新串口列表以及对状态进行修改。
布局优化: 使用Panel容器优化界面布局,是的波形显示和接收显示界面分开可以自由来回切换。
波形显示逻辑: 修改波形显示逻辑,我们可以在使用串口的同时选择是否开启波形显示(之前是在打开串口前进行选择)
滚轮控制显示区域: 增添了利用滚轮控制波形的显示范围,之前只能利用滑条来控制区域。 傅里叶变换:
增加了对指定区域的傅里叶变换功能,将时域图转换成频域图。
** 保存图表: ** 可以保存我们的波形图到我们的文件夹中。
** 数据统计: ** 增加了统计波形显示区域内的最大值与最小值(后续可能更新更多的统计数据)
此外还有许多地方尚未完成,例如自定义数据帧解析,多行发送,高速模式下时间戳的使用等等~欢迎大家提出建议,会多多吸取意见并修改。 以下展示部分源码:
private void Chart1_MouseEnter(object sender, EventArgs e) { chart.MouseWheel += Chart1_MouseWheel; }
private void Chart1_MouseLeave(object sender, EventArgs e) { chart.MouseWheel -= Chart1_MouseWheel; }
private void Chart1_MouseWheel(object sender, MouseEventArgs e) { try { if (e.Delta < 0) // 向下滚动 { // 增加 chartLength 的值,可以根据需要调整增加的步长 ChartLenth += 100; } else if (e.Delta > 0) // 向上滚动 { // 减小 chartLength 的值,可以根据需要调整减小的步长 ChartLenth -= 100;
if (ChartLenth < 100) // 防止 chartLength 变得太小 { ChartLenth = 100; } }
} catch (Exception ex) { // 处理异常 MessageBox.Show("发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
这里是为波形图绑定滚轮,检测滚轮的状态来改变ChartLenth的大小,根据ChartLenth的大小来改变波形的显示区域。
private void SaveChart_Click(object sender, EventArgs e) { if (chart.Series.Count > 0) { using (SaveFileDialog saveFileDialog = new SaveFileDialog()) { saveFileDialog.Filter = "PNG Files (*.png)|*.png|All Files (*.*)|*.*"; saveFileDialog.DefaultExt = "png"; saveFileDialog.Title = "Save Chart Image";
if (saveFileDialog.ShowDialog() == DialogResult.OK) { SaveChartImage(chart, saveFileDialog.FileName); MessageBox.Show("图表已成功保存为图片!", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information); } } } } private void SaveChartImage(Chart chart, string filePath) { try { // 使用 SaveImage 方法保存图表为图片 chart.SaveImage(filePath, ChartImageFormat.Png); } catch (Exception ex) { // 处理保存异常 MessageBox.Show("保存图片时发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
图片保存部分的代码,启用资源管理器来获取我们的保存信息,之后利用chart控件自带保存控件的方法来保存我们的控件。
private void FuChange_Click(object sender, EventArgs e) { int Xmax = int.Parse(MAXArea.Text); int Xmin = int.Parse(MinArea.Text);
if (Xmax < Xmin || Xmin < 0) { MessageBox.Show("请输入正确的范围"); return; }
if (chart.Series.Count == 0) { MessageBox.Show("图表中没有可用的系列"); return; }
// 获取选定范围内的数据点 List<DataPoint> selectedDataPoints = new List<DataPoint>(); foreach (DataPoint dataPoint in chart.Series[0].Points) { if (dataPoint.XValue >= Xmin && dataPoint.XValue <= Xmax) { selectedDataPoints.Add(dataPoint); } }
// 将数据点转换为复数数组 Complex[] complexData = new Complex[selectedDataPoints.Count]; for (int i = 0; i < selectedDataPoints.Count; i++) { complexData[i] = new Complex(selectedDataPoints[i].YValues[0], 0); }
// 执行傅里叶变换 Fourier.Forward(complexData, FourierOptions.Matlab);
// 将结果显示在 FuChart 上 FuChart.Series.Clear(); WindowsFormsSeries fuSerial = new WindowsFormsSeries("傅里叶变换结果"); fuSerial.ChartType = SeriesChartType.FastLine; fuSerial.BorderWidth = 3; FuChart.Series.Add(fuSerial);
// 计算频率间隔 double frequencyInterval = 1.0 / (selectedDataPoints[1].XValue - selectedDataPoints[0].XValue);
// 显示正频率部分 for (int i = 0; i < complexData.Length/2; i++) { double frequency = i * frequencyInterval; FuChart.Series[0].Points.AddXY(frequency, complexData[i].Magnitude); }
// 设置 X 轴的间隔 FuChart.ChartAreas[0].AxisX.Interval = frequencyInterval;
// 刷新 Chart FuChart.Invalidate(); }
加入数学库,我们可以对我们的指定长度的数据进行离散傅里叶变换,将数据转为复数形式,之后进行傅里叶变换,将傅里叶变换的结果保存到新的Serial集合中并添加到相关的chart控件上。