c|C#实现串口通讯实时显示波形并实现平滑滤波和50Hz滤波
实现单片机与电脑通讯,通过串口接收。
主界面:
文章图片
绘制界面:
文章图片
在主界面设置串口号以及波特率,点击打开串口,再点击波形显示,即可显示通过串口过来的数据波形。
主界面源码:
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 = https://www.it610.com/article/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)
{
}
}
}
绘制界面源码:
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
private List
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标志位
}
}
}
【c|C#实现串口通讯实时显示波形并实现平滑滤波和50Hz滤波】这是之前做实验的时候写的,现在想起来发一下,当时的的效果图没有保存。
推荐阅读
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- MybatisPlus使用queryWrapper如何实现复杂查询
- python学习之|python学习之 实现QQ自动发送消息
- 孩子不是实现父母欲望的工具——林哈夫
- opencv|opencv C++模板匹配的简单实现
- Node.js中readline模块实现终端输入
- java中如何实现重建二叉树
- 人脸识别|【人脸识别系列】| 实现自动化妆
- paddle|动手从头实现LSTM
- pytorch|使用pytorch从头实现多层LSTM