用监听的方法接收数据,如果对方发送的字符比较长,接收的字符就会有丢失,短点的还正常
先附上我的代码
public partial class Form1 : Form
{
public delegate void HandleInterfaceUpdateDelegate(string text);
private HandleInterfaceUpdateDelegate interfaceUpdateHandle;
SerialPort sp = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One); public Form1()
{
InitializeComponent();
} private void BtnSend_Click(object sender, EventArgs e)
{
sp.Write(this.textBox1.Text);
} private void Form1_Load(object sender, EventArgs e)
{
if (!sp.IsOpen)
{
sp.Close();
sp.Open();
}
} private void UpdateLabel(string text)
{
this.LabReceive.Text = text;
} private void BtnAny_Click(object sender, EventArgs e)
{
interfaceUpdateHandle = new HandleInterfaceUpdateDelegate(UpdateLabel);
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
sp.ReceivedBytesThreshold = 1;
} void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] readBuffer = new byte[sp.ReadBufferSize]; sp.Read(readBuffer, 0, readBuffer.Length);
this.Invoke(interfaceUpdateHandle, new string[] { Encoding.UTF8.GetString(readBuffer) });
} private void BtnReceive_Click(object sender, EventArgs e)
{
this.LabReceive.Text = sp.ReadExisting();
}
比如对方发送uuuuxxxxxkkkkk,我这边接收的就成了kkk。
先附上我的代码
public partial class Form1 : Form
{
public delegate void HandleInterfaceUpdateDelegate(string text);
private HandleInterfaceUpdateDelegate interfaceUpdateHandle;
SerialPort sp = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One); public Form1()
{
InitializeComponent();
} private void BtnSend_Click(object sender, EventArgs e)
{
sp.Write(this.textBox1.Text);
} private void Form1_Load(object sender, EventArgs e)
{
if (!sp.IsOpen)
{
sp.Close();
sp.Open();
}
} private void UpdateLabel(string text)
{
this.LabReceive.Text = text;
} private void BtnAny_Click(object sender, EventArgs e)
{
interfaceUpdateHandle = new HandleInterfaceUpdateDelegate(UpdateLabel);
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
sp.ReceivedBytesThreshold = 1;
} void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] readBuffer = new byte[sp.ReadBufferSize]; sp.Read(readBuffer, 0, readBuffer.Length);
this.Invoke(interfaceUpdateHandle, new string[] { Encoding.UTF8.GetString(readBuffer) });
} private void BtnReceive_Click(object sender, EventArgs e)
{
this.LabReceive.Text = sp.ReadExisting();
}
比如对方发送uuuuxxxxxkkkkk,我这边接收的就成了kkk。
在sp_DataReceived里设置断点;另外,接收的可以改为:sp.Read(readBuffer, 0, sp.ReadBufferSize);
我以前碰到情况,byte[] readBuffer = new byte[sp.ReadBufferSize]; sp.Read(readBuffer, 0, readBuffer.Length);
这两步之间sp.ReadBufferSize得值会有变化,
byte[] arraybyte = new byte[nByteNum];
serialPort1.Read(arraybyte, 0, nByteNum);
{
thread.sleep(500);
byte[] readBuffer = new byte[sp.ReadBufferSize]; sp.Read(readBuffer, 0, readBuffer.Length);
this.Invoke(interfaceUpdateHandle, new string[] { Encoding.UTF8.GetString(readBuffer) });
}
这样不好吧,要是经常性的接收,程序岂不总卡在那。
如果把这句this.LabReceive.Text = text 改成this.LabReceive.Text = this.LabReceive.Text + text 就不会出现那个问题。 但清空LabReceive就成了问题,如果将this.LabReceive.Text =""写到sp_DataReceived方法里,会报:“从不是创建控件LabReceive的线程访问它。” ,sp_DataReceived是调用了另一个线程,加了事件委托又成了起初那样的问题。
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
的工作原理你要明白,接收事件的触发条件并不一定是个确切的条件。 有时接收几个字节就激活,有时接收n个字节激活。 这时候,接收缓冲区并没有填充多少数据, 很可能出现字节接收不完全的情况。 300或者500毫秒基本都可以满足接收缓冲区的填充需要。 对于300-500 毫秒的等待,sleep 尚可接受。 串口通信不可靠,不抗干扰的特点决定了它绝对不可能像 udp,tcp 那样处理得十分平滑流畅。但也不至于像你说的卡在那。
{
if (txtMain.InvokeRequired)
{
ReceivData dl = new ReceivData(RefreshForReceive);
object arg = bytes;
txtMain.Invoke(dl, arg);
}
else
{
foreach (byte b in bytes)
{
txtMain.Text += String.Format("{0:X2} ",b);
}
txtMain.Text += "\r\n";
}
} void _com_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int bytesRead = 0;
_com.ReceivedBytesThreshold = 100000; //关掉串口接收事件
while (true)
{
if (bytesRead > 65535)
bytesRead = 0; try
{
receiveBuffer[bytesRead] = (byte)_com.ReadByte();
++bytesRead;
}
catch (TimeoutException)
{
break;
}
catch
{
_com.ReceivedBytesThreshold = 1;
return;
}
}
if (bytesRead > 0)
{
byte[] bytes = new byte[bytesRead];
Array.Copy(receiveBuffer, 0, bytes, 0, bytesRead);
Array.Clear(receiveBuffer, 0, bytesRead);
RefreshForReceive(bytes);
}
bytesRead = 0;
_com.ReceivedBytesThreshold = 1;
}
这是我自己写串口调试工具的时候写的两个方法 !!你可以参考一下 !!ReceivData 是一个委托!!!!
thread.sleep(500);
变量与缓冲区接收字节大小比较,缓冲区大,跳到上面,相等然后读数据区数据,出了数据