目录
UI布局
1.串口的读写
2.串口扫描函数
3.实时刷新UI
3.1定时器刷新
3.2委托+timer类
背景:在已有基础上将串口读写数据封装到一个类或者方法里,添加UI实时更新数据的功能,添加可设置参数的功能,添加可查询状态的功能
UI布局
引用Sunny UI包对UI界面重新绘制
Sunny UI官网
串口的读写
private bool WriteAndReadPort(string cmd, out string result)
{
//读写
result = null;
try
{
if (serialPort1?.IsOpen == true)
{
lock (serialLock)
{
serialPort1.DiscardInBuffer();
serialPort1.DiscardOutBuffer();
serialPort1.Write(cmd);
Thread.Sleep(200);
result = serialPort1.ReadExisting();
}
return result?.Length > 0;
}
return false;
}
catch (Exception)
{
result = null;
return false;
}
}
串口扫描
private void SearchPortToComBox(ComboBox MyBox,SerialPort MyPort)
{
//扫描
MyBox.DataSource = SerialPort.GetPortNames();
}
所遇问题及解决办法
因为是对串口返回的数据是以ReadExisting()来进行读取;
官网解释:
在编码的基础上,读取 SerialPort 对象的流和输入缓冲区中所有立即可用的字节。
返回 String
SerialPort 对象的流和输入缓冲区的内容。
1.当下位机返回的数据量大时,接受到的数据可能会发生错乱。比如A发送的指令本应该是返回给A的,结果因为B也做了发送指令的操作,此时原本是返回给A的数据被B接收到。
解决办法:对串口读写加上线程锁,这样就能确保每次的读写不会错乱
2.或是有特殊的帧头 帧尾,这时就需要对数据进行一个拆包的操作
(略...)
实时刷新UI
3.1定时器刷新(不推荐)
3.2委托+timer类(测试)
private void Form1_Load(object sender, System.EventArgs e)
{
Thread t = new Thread(new ThreadStart(GetData));
t.IsBackground = true; //后台
t.Start();
}
private void GetData()
{
var timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.Enabled = true;
timer.AutoReset = true;//设置是执行一次(false)还是一直执行(true);
timer.Start();
timer.Elapsed += (o , e) =>
{
SetData();
ShowMessage(string.Format("更新时间:" + DateTime.Now));
};
}
// 声明委托
private delegate void SetDataDelegate();
private void SetData()
{
if (this.InvokeRequired) //当InvokeRequired为true时,说明在非创建线程访问当前UI控件
{
this.Invoke(new SetDataDelegate(SetData));
}
else
{
LB1.Text = string.Format("更新时间:" + DateTime.Now);
}
}
//声明委托
private delegate void ShowMessageDelegate(string message);
private void ShowMessage(string message)
{
if (this.InvokeRequired)
{
ShowMessageDelegate showMessageDelegate = ShowMessage;
this.Invoke(showMessageDelegate, new object[] { message });
}
else
{
TB1.Text = message;
}
}
3.3异步
异步部分代码:
Serial_OC();
if (watchTaskRunning)
{
Source.Cancel();
btTemp.BeginInvoke(new Action(() => { btTemp.Text = "Temp"; }));
watchTaskRunning = false;
}
else
{
btTemp.BeginInvoke(new Action(() => { btTemp.Text = "Stop"; }));
Source = new CancellationTokenSource();
var token = Source.Token;
Task.Run(() =>
{
while (true)
{
if (token.IsCancellationRequested)
{
break;
}
else
{
if (WriteAndReadPort("Temp\r", out string res))
{
if (double.TryParse(res, out double tempRes))
{
//查询控制板温度
tb_Temp.BeginInvoke(new Action(() => { tb_Temp.Text = tempRes.ToString() + "℃"; }));
Thread.Sleep(1000);
}
}
}
}
}, token);
watchTaskRunning = true;
}
最后F5跑起来,没有调试的机器,可以下一个有人虚拟串口
安装完毕后新建一个串口, 这里我们选择第一个
打开我们之前用Socket+WPF做好的模拟下位机的程序
地址---Win+R---ipconfig---自己本机IP,端口就是创建出来模拟串口的的端口
测试上图:
选择COM1——打开串口:
文章来源:https://www.toymoban.com/news/detail-440685.html
文章来源地址https://www.toymoban.com/news/detail-440685.html
到了这里,关于串口通信助手优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!