功能实现

实现单片机与电脑通讯,通过串口接收。并显示通过串口过来的数据波形

主界面

在主界面设置串口号以及波特率,点击打开串口,再点击波形显示,即可显示通过串口过来的数据波形。

主界面源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace _3
{
public delegate void ShowWindow();
public delegate void HideWindow();
public delegate void OpenPort();
public delegate void ClosePort();
public delegate Point GetMainPos();
public delegate int GetMainWidth();

public partial class MainForm : Form
{
Drawer Displayer;
public MainForm()
{
InitializeComponent();
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; //操控线程
}


private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
byte[] data = new byte[serialPort1.BytesToRead]; //定义缓冲区,因为串口事件触发时有可能收到不止一个字节
serialPort1.Read(data, 0, data.Length);
if (Displayer != null)
Displayer.AddData(data);

}

private void CreateNewDrawer()//创建ADC绘制窗口
{
Displayer = new Drawer();//创建新对象

Displayer.Show();//显示窗口
}

private void CreateDisplayer()
{
this.Left = 0;
CreateNewDrawer();
Rectangle Rect = Screen.GetWorkingArea(this);

}

private void button2_Click(object sender, EventArgs e)
{
try
{
serialPort1.PortName = comboBox1.Text; //端口号
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text); //波特率
serialPort1.Open(); //打开串口
button2.Enabled = false;
button3.Enabled = true;
}
catch
{
MessageBox.Show("端口错误", "错误");
}
}

private void button3_Click(object sender, EventArgs e)
{
try
{
serialPort1.Close(); //关闭串口 //关闭串口
button2.Enabled = true;
button3.Enabled = false;
}
catch //一般关闭串口不会出错,故而不用编程
{
}
}

private void Form1_Load(object sender, EventArgs e)
{
for (int i = 1; i < 6; i++)
{
comboBox1.Items.Add("COM" + i.ToString()); //添加串口
}
comboBox1.Text = "COM1"; //默认选项
comboBox2.Text = "4800";

}

private void button1_Click(object sender, EventArgs e)
{
if (Displayer == null)//第一次创建Displayer = null
{
CreateDisplayer();
}
else
{
if (Displayer.IsDisposed)//多次创建通过判断IsDisposed确定串口是否已关闭,避免多次创建
{
CreateDisplayer();
}
}
}

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}


}
}

绘制界面

绘制界面源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace _3
{
public partial class Drawer : Form
{
private const int Unit_length = 22;//单位格大小
private int DrawStep = 5;//默认绘制单位
private const int Y_Max = 255;//Y轴最大数值
private const int MaxStep = 30;//绘制单位最大值
private const int MinStep = 1;//绘制单位最小值
private const int StartPrint = 32;//点坐标偏移量
private List<byte> DataList = new List<byte>();//数据结构----线性链表
private List<byte> DataListZH = new List<byte>();//数据结构----线性链表
private Pen LinesPen = new Pen(Color.FromArgb(0xaa, 0x00, 0x00));//波形颜色
private bool KeyShift, KeyStepUp, KeyStepDown;


public Drawer()
{
this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);//开启双缓冲

this.UpdateStyles();
InitializeComponent();
}

public void AddData(byte[] Data) //将MainForm的数据推送过来
{

for (int i = 0; i < Data.Length; i++)
DataList.Add(Data[i]);//链表尾部添加数据

Invalidate();//刷新显示
}

private void Drawer_Load(object sender, EventArgs e)
{
}




private void Drawer_Paint(object sender, PaintEventArgs e) //绘制
{
//String Str = "";
e.Graphics.FillRectangle(Brushes.White, e.Graphics.ClipBounds); //将整个窗口定义为白色


if (DataList.Count - 1 >= (this.ClientRectangle.Width - StartPrint) / DrawStep)//如果数据量大于可容纳的数据量,即删除最左数据
{
DataList.RemoveRange(0, DataList.Count - (this.ClientRectangle.Width - StartPrint) / DrawStep - 1);
}

byte[] DataListt = DataList.ToArray();
int[] D = new int[DataListt.Length];

for (int i = 0; i < DataListt.Length; i++)
{
int m = DataListt[i];
D[i] = m;
}


int[] D2 = new int[DataListt.Length];

//500采样频率的50Hz陷波
double[] B = new double[3] { 0.96897915136010271, -1.5678412012906751, 0.96897915136010271 };
double[] A = new double[3] { 1, -1.5678412012906751, 0.93795830272020542 };
double W1 = 0;
double W2 = 0;
double W3 = 0;

for (int i = 0; i < DataListt.Length; i++)
{
W1 = A[0] * D[i] - A[1] * W2 - A[2] * W3;
double s = Math.Floor(B[0] * W1 + B[1] * W2 + B[2] * W3);
D2[i] = (int)s;
W3 = W2;
W2 = W1;
}
W1 = 0;
W2 = 0;
W3 = 0;

//平滑
int[] D3 = new int[DataListt.Length];
D3 = D2;
for (int i = 2; i < DataListt.Length - 3; i++)
{
int s = D2[i - 2] + D2[i - 1] + D2[i] + D2[i + 1] + D2[i + 2] ;
D3[i] = s / 5;

}


//数据入组
for (int i = 0; i < D3.Length; i++)
{
byte[] M = BitConverter.GetBytes(D3[i]);
DataListZH.Add(M[0]);
Invalidate();
}


if (DataListZH.Count - 1 >= (this.ClientRectangle.Width - StartPrint) / DrawStep)//如果数据量大于可容纳的数据量,即删除最左数据
{
DataListZH.RemoveRange(0, DataListZH.Count - (this.ClientRectangle.Width - StartPrint) / DrawStep - 1);
}

for (int i = 0; i < DataListZH.Count - 1; i++) //绘制波形
{
e.Graphics.DrawLine(LinesPen, StartPrint + i * DrawStep, 17 * Unit_length - DataListZH[i]*3 , StartPrint + (i + 1) * DrawStep, 17 * Unit_length - DataListZH[i + 1]*3 ); //绘制一条连接由坐标对指定的两个点的线条
//(波形颜色,x1,y1,x2,y2)
}
}

private void Drawer_KeyDown(object sender, KeyEventArgs e)
{
if (e.Shift)//shift功能键按下
KeyShift = true;//标志位置位
switch (e.KeyCode)//功能标志置位
{
case Keys.Up://放大波形
KeyStepUp = true;
break;
case Keys.Down://缩小波形
KeyStepDown = true;
break;
default:
break;
}
}

private void Drawer_KeyUp(object sender, KeyEventArgs e)
{
if (KeyShift)
{

if (KeyStepUp)
{
if (DrawStep < MaxStep)//绘制单位递增
DrawStep++;
Invalidate();
KeyStepUp = false;
}
else
{
if (KeyStepDown)
{
if (DrawStep > MinStep)//绘制单位递减
DrawStep--;
Invalidate();
KeyStepDown = false;
}

}

}
else//如果是其他按键,清空所有标志位
{
KeyStepUp = false;
KeyStepDown = false;
}
KeyShift = false;//清空shift标志位
}
}
}

使用说明

问题一:复制程序后没有效果

A:需要对事件进行绑定!在设计窗口下,点击事件按钮(带闪电图标),然后分别将对应函数和事件联系起来
KeyDown->Drawer_KeyDown、KeyUp->Drawer_KeyUp、Paint->Drawer_Paint,而后 Invalidate 刷新显示才有效


相关链接

  1. C#实现串口通讯实时显示波形并实现平滑滤波和50Hz滤波

=================我是分割线=================

欢迎到公众号来唠嗑: