需求
erp通过com口与地磅连接,地磅每隔100ms传送一串子节数据给erp,erp显示数据稳定后对数据进行保存
难点
由于串口传输速度没有电脑处理的速度快,如果电脑也实时触发读取数据的方法就会造成数据的不完整
原因
当erp打开串口,数据就会存到缓存中,若一直不处理就一直存在缓存中,一旦通过serialPort.Read()进行读取就会清理缓存继而读取下一次的串口数据,就这个原因,数据有时会只读到串口传过来完整数据的其中一部分,这造成了显示不完整的情况
解决
比较简单粗暴的方法就是通过 Thread.Sleep();延时,等待串口发送完再做处理,延时时间要看串口的发送频率而定
具体实现代码如下
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;//设置该属性 为false
}
private void Form1_Load(object sender, EventArgs e)
{
RegistryKey keyCom = Registry.LocalMachine.OpenSubKey("Hardware\\DeviceMap\\SerialComm");
if (keyCom != null)
{
string[] sSubKeys = keyCom.GetValueNames();
cmbPort.Items.Clear();
foreach (string sName in sSubKeys)
{
string sValue = (string)keyCom.GetValue(sName);
cmbPort.Items.Add(sValue);
}
if (cmbPort.Items.Count > 0)
cmbPort.SelectedIndex = 0;
}
cmbBaud.Text = "9600";
}
bool isOpened = false;//串口状态标志
private void button1_Click(object sender, EventArgs e)
{
if (!isOpened)
{
serialPort.PortName = cmbPort.Text;
serialPort.BaudRate = Convert.ToInt32(cmbBaud.Text, 10);
try
{
serialPort.Open(); //打开串口
button1.Text = "关闭串口";
cmbPort.Enabled = false;//关闭使能
cmbBaud.Enabled = false;
isOpened = true;
serialPort.DataReceived += new SerialDataReceivedEventHandler(post_DataReceived);//串口接收处理函数
}
catch
{
MessageBox.Show("串口打开失败!");
}
}
else
{
try
{
serialPort.Close(); //关闭串口
button1.Text = "打开串口";
cmbPort.Enabled = true;//打开使能
cmbBaud.Enabled = true;
isOpened = false;
}
catch
{
MessageBox.Show("串口关闭失败!");
}
}
}
string f = "";
private void post_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
string s = "";
Thread.Sleep(80);//用来读取完数据的字节数
int byteNumber = serialPort.BytesToRead;
//延时等待数据接收完毕。
while ((byteNumber < serialPort.BytesToRead) && (serialPort.BytesToRead < 4800))
{
byteNumber = serialPort.BytesToRead;
Thread.Sleep(20);//用来每个字节给多少时间处理
}
int n = serialPort.BytesToRead; //记录下缓冲区的字节个数
byte[] data = new byte[n];
serialPort.Read(data, 0, n);
foreach (byte item in data)
{
s += Convert.ToChar(item);
}
f = s;
this.ReceiveTbox.Text = s.ToString();
}
catch (Exception ee)
{
}
}
private void button2_Click(object sender, EventArgs e)
{
string d = f;
this.Close();
}
private void button3_Click(object sender, EventArgs e)
{
SendTbox.Text = f;
}
}
}