您的位置:首页 > 编程语言 > C#

C#中使用seriport和单片机进行串口长数据收发不全,解决办法

2017-08-13 11:40 513 查看
最近做了一个项目,上位机向单片机要205个字节的报文。每次上位机接收的数据总是分成好几段,不能一次接收205个字节。所以对数据处理造成影响。因此就想着怎么能实现一次接收205字节数据,一次进行处理。试了很多办法,最后终于解决了。

C#中,使用的是serialPort.DataReceived来接收数据。一开始,上位机向单片机发送轮询指令后,单片机按照modbus协议上传205个字节数据。但是每次上位机将数据分成32个字节一段的形式接收。找了半天原因,最终发现,由于计算机速度很快,但是单片机发送205个字节数据是有一个过程的。然而,上位机收到一个字节就会触发serialPort.DataReceived,这时上位机去读接收缓冲区时,时间刚好只能读取32个字节。所以,我在接收一开始进行了延时,使用了 System.Threading.Thread.Sleep(300);延时300后,发现一次能够完整的接收205个字节数据。

分析了一下,原因可能是上位机接收完205个字节需要的时间在300毫秒,如果不延时,直接去读的话,只能读到目前接收的32个字节。具体看程序吧!

/// <summary>
/// 接收数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void serialport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
//***正在接收状态指示。
IsReceving = true;
//等待所有数据全部进入缓冲区
System.Threading.Thread.Sleep(300);

//读入收到的数据。
int Len = serialport.BytesToRead;
if (Len < 1)
{
//***接收完成状态指示。
IsReceving = false;
return;
}

byte[] data = new byte[Len];
serialport.Read(data, 0, Len);

//字符串处理。
string Str = Encoding.GetEncoding("GB2312").GetString(data);

//数据转十六进制字符串。
string Hex = string.Empty;
for (int i = 0; i < data.Length; i++)
{
string tempstr = Convert.ToString(data[i], 16);
if (tempstr.Length < 2)
{
tempstr = '0' + tempstr;
}
Hex += tempstr + ' ';
}
Hex = Hex.ToUpper();

//使用委托跨线程读取数据。
rtbxRecStr.Invoke(new EventHandler(delegate
{
//***正在处理字符串。
DoingStr = true;

rtbxRecStr.AppendText(Str);
if (chkbxAutoClr.Checked && rtbxRecStr.Text.Length > 10000)
{
rtbxRecStr.Text = string.Empty;
}
//将控件的内容滚动到当前位置。
rtbxRecStr.ScrollToCaret();
//***完成处理字符串。
DoingStr = false;
}
));
// Logger.Debug(string.Format("接收数据: {0}", Str));

rtbxRecHex.Invoke(new EventHandler(delegate
{
//***正在处理十六进制数据。
DoingHex = true;

rtbxRecHex.AppendText(Hex);
if (chkbxAutoClr.Checked && rtbxRecHex.Text.Length > 10000)
{
rtbxRecHex.Text = string.Empty;
}
//将控件的内容滚动到当前位置。
rtbxRecHex.ScrollToCaret();
//***完成处理十六进制数据。
DoingHex = false;
}
));
Logger.Debug(string.Format("接收数据: {0}", Hex));

while (DoingStr || DoingHex)
{
//处理串口接收事件及其它系统消息。
Application.DoEvents();
}
//***接收完成状态指示。
IsReceving = false;
}
catch (Exception Err)
{
MessageBox.Show(Err.Message, "串口调试助手");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: