一、简介
结合了我之前的一篇博客,在C#中,下面的几个接收函数,读取接收缓存器时,会发生超时异常。比如:
private void Recieve(object sender, SerialDataReceivedEventArgs e)
{
try
{
#region 以下5种方法,实用性不广,不建议采用。如果要用,可以参考官网
//string s2 = SerialPortObj.ReadLine();//读取接收缓存器中的新行的值。超时会发生异常。
//string s3 = SerialPortObj.ReadTo("XXX");//读取接收缓存器中的特定字符串的值。超时会发生异常。
//string s1 = SerialPortObj.ReadExisting();//读取接收缓存器中的所有字节,并将其转换为字符串。超时不会发生异常
//int i1 = SerialPortObj.ReadByte();//读取一个字节并返回整数,超时会发生异常。
//int i2 = SerialPortObj.ReadChar();//读取一个字符并返回整数,超时会发生异常。
#endregion
#region 建议采用第6种方法
开辟接收缓冲区
byte[] bytReceiveData = new byte[SerialPortObj.BytesToRead];
SerialPortObj.Read(bytReceiveData, 0, bytReceiveData.Length); //从串口读取数据
//一旦接收彩屏的曝光指令,PC马上返回当前的曝光值
SendExposeValues(bytReceiveData);
//调用委托,将字符信息显示在TextBox控件上。
_recievedData = System.Text.Encoding.Default.GetString(bytReceiveData);
Dispatcher.Invoke(DispatcherPriority.Send, new UpdateUiTextDelegate(WriteDate), _recievedData);
#endregion
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
前5个方法,局限性比较大,不如第六哥方法使用,建议采用第六个方法。
二、超时异常函数及其应用
关于前三个方法,是超时方法。
我们先来看看超时异常,看看每个接收函数超时的效果。以下操作,用串口助手发数据进行测试:
2.1、SerialPortObj.ReadExisting();//读取接收缓存器中的所有字节,并将其转换为字符串。超时不会发生异常。
其他省略,见官网的超时问题:
https://blog.csdn.net/xpj8888/article/details/84628762(我的上一篇博客)
三、如何在特定时间内,非阻塞提取接收缓存器里面的全部有效字节?
注意啊,本章节的标题,我用到了下面的4个关键词:
-
特定时间——间隔特性时间(经验值500ms)扫描一次缓存器,直到收完,保证完整信息。
-
接收缓存器——缓存器一旦有数据,会触发事件接收serialPortObj.DataReceive+= receive()
-
有效字节——确保数据包的完整,避免拆包。
-
非阻塞——线程接收,防止阻塞
要接收字节,必须用下面的 SerialPortObj.Read这个函数:
byte[] bytReceiveData = new byte[SerialPortObj.BytesToRead];
SerialPortObj.Read(bytReceiveData, 0, bytReceiveData.Length); //从串口读取数据
但是,怎么理解 提取接收缓存器里面的全部有效字节?那就是,假如我发送了10字节有效字节,接收缓存器可能第一次接收3个字节,第二次可能接收7个字节。那么3 + 7 = 10,才是我的完整信息。那该怎么办呢?我应该一直读取接收缓存器,分别把3和7都放在一个接收队列中,直到接收缓存器没有收到任何信息,这时,接收队列中的10个字节才是有效的、才是完整的。
https://bbs.csdn.net/topics/320016645
https://bbs.csdn.net/topics/390730988?locationNum=6&fps=1