// 昨天的comport.ReadExisting()问题困扰着我,如何读取到完整的PLC代码呢?今天终于解决了。我的思路还是对着的,不停地读取缓冲区的数据,直到把完整的代码读完。但是忽略了port_StringDataReceived时间的触发问题,再找到 ReceivedBytesThreshold关键词后进行了搜索,理解了port_StringDataReceived事件的控制,然后就是写不停地读取缓冲区的数据,直到把完整的代码读完的算法,这里要说的是,半路出家很多细节问题要解决,我刚开始只是注意功能的实现,没有注意捕捉程序异常,处理异常,使得程序不能完整的运行。再经历了一上午的努力终于实现了数据的监测,就是速率有点慢。这都是单线程惹的祸,看来还得学习一下后台线程的使用。 // 下面是我的代码,这里要感谢SCDN论坛的 Yali8 网友,他的算法的完整性很高,我在他的基础上进行了修改,得到了我想要的代码。还要感谢网友 剑客 QQ:316722224 ,给我的耐心解答。下面分享一下我的成果~ //代码生活之使用ReadExisting()读取缓冲区内PLC响应的完整代码
// ReceivedBytesThreshold只是触发DataReceived事件的一个阀值,由于串口通讯的实时性,很难说你每次读取的数据长度就是阀值的长度。请参考下面的方法。 //一、技术要点:
//(1).首先,SerialPort的ReceivedBytesThreshold先设置成1,表示只要有1个字符送达端口时便触发DataReceived事件
//(2).当DataReceived触发时,先把ReceivedBytesThreshold设置成一个比较大的值,达到读取本次端口数据时,不再触发DataReceived.
//(3).循环读取端口中的数据,直至读完。
//(4).移除读取数据中的非法字符。
//(5).触发一个后台线程处理收到的数据。
//(6).在finally中把ReceivedBytesThreshold重置回1
//二、C# Code //调用将代码翻译为数据的子程序,返回值为带符号十进制整数
//if (PLCCode.Length == 25)
//{
// data = PLCCodeToStringData(PLCCode);
// string LWA = data[0];
// string RWA = data[1];
// LogMonitoringPage(LWA, RWA); // 显示有效信息到监测界面 //}
//Log(LogMsgType.Incoming, PLCCode); // 显示所有信息
// ReceivedBytesThreshold只是触发DataReceived事件的一个阀值,由于串口通讯的实时性,很难说你每次读取的数据长度就是阀值的长度。请参考下面的方法。 //一、技术要点:
//(1).首先,SerialPort的ReceivedBytesThreshold先设置成1,表示只要有1个字符送达端口时便触发DataReceived事件
//(2).当DataReceived触发时,先把ReceivedBytesThreshold设置成一个比较大的值,达到读取本次端口数据时,不再触发DataReceived.
//(3).循环读取端口中的数据,直至读完。
//(4).移除读取数据中的非法字符。
//(5).触发一个后台线程处理收到的数据。
//(6).在finally中把ReceivedBytesThreshold重置回1
//二、C# Code //调用将代码翻译为数据的子程序,返回值为带符号十进制整数
//if (PLCCode.Length == 25)
//{
// data = PLCCodeToStringData(PLCCode);
// string LWA = data[0];
// string RWA = data[1];
// LogMonitoringPage(LWA, RWA); // 显示有效信息到监测界面 //}
//Log(LogMsgType.Incoming, PLCCode); // 显示所有信息
{
comport.ReceivedBytesThreshold = comport.ReadBufferSize;
while (true)
{
strReceive = comport.ReadExisting();
if (string.Equals(strReceive, string.Empty))
{
break;
}
else
{
PLCCode += strReceive;
Application.DoEvents();
Thread.Sleep(100);
}
}
PLCCode = PLCCode.Replace("\0", string.Empty); //去除非法符号,本例可以不要。
PLCCode = PLCCode.Replace("\r\n", string.Empty);
PLCCode = PLCCode.Replace("\r", string.Empty);
PLCCode = PLCCode.Replace("\n", string.Empty);
utPrint.Print(PLCCode);
//if (!this.bIsHandleCom) //后台进程处理数据,需要学习
//{
// this.bIsHandleCom = true;
// mReceiveData = strCollect;
// if (ReceiveDataParserEvent != null)
// ReceiveDataParserEvent(mReceiveData);
// if (ThreadReceiveParser != null && !ThreadReceiveParser.IsAlive)
// {
// ThreadReceiveParser.Start();
// }
//} }
catch (Exception ex)
{
MessageBox.Show( ex.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
comport.ReceivedBytesThreshold = 1;
}
我们没有校验,只有数据包头和包尾,而且某一种指令得到的数据长度一定的(有很多指令,数据长度不一),每次都我都是把数据放到ArrayList数组中,先找头,然后找尾,如果找到了,就去处理,但数据经常丢一两个字节,不知道是在加入ArrayList数组时出错,还是什么原因
我们没有校验,只有数据包头和包尾,而且某一种指令得到的数据长度一定的(有很多指令,数据长度不一),每次都我都是把数据放到ArrayList数组中,先找头,然后找尾,如果找到了,就去处理,但数据经常丢一两个字节,不知道是在加入ArrayList数组时出错,还是什么原因看看你是怎么接收数据并加到ArrayList里的
我是接过来后,放在arrlist中,然后判断,如果没达到要求,先是等待继续往arrlist中添加,最后如果数据不对,就会重发指令,目前经常会出现数据读不完,原因还在查找
我们没有校验,只有数据包头和包尾,而且某一种指令得到的数据长度一定的(有很多指令,数据长度不一),每次都我都是把数据放到ArrayList数组中,先找头,然后找尾,如果找到了,就去处理,但数据经常丢一两个字节,不知道是在加入ArrayList数组时出错,还是什么原因看看你是怎么接收数据并加到ArrayList里的我是一个字节就触发事件,然后int count =serialport.read(buffer,0,bytestoread),然后dispose(buffer)
我是接过来后,放在arrlist中,然后判断,如果没达到要求,先是等待继续往arrlist中添加,最后如果数据不对,就会重发指令,目前经常会出现数据读不完,原因还在查找
建议是定义一个大一点的byte数组,接收到数据就往里面写,然后你再到byte数组里面去查找和做一些处理,处理完一个完整包就把那部分从byte数组里面移除
我们没有校验,只有数据包头和包尾,而且某一种指令得到的数据长度一定的(有很多指令,数据长度不一),每次都我都是把数据放到ArrayList数组中,先找头,然后找尾,如果找到了,就去处理,但数据经常丢一两个字节,不知道是在加入ArrayList数组时出错,还是什么原因看看你是怎么接收数据并加到ArrayList里的我是一个字节就触发事件,然后int count =serialport.read(buffer,0,bytestoread),然后dispose(buffer)得把buffer添加到ArrayList里,收到的每个字节都要加到ArrayList,然后去分析ArrayList
我们没有校验,只有数据包头和包尾,而且某一种指令得到的数据长度一定的(有很多指令,数据长度不一),每次都我都是把数据放到ArrayList数组中,先找头,然后找尾,如果找到了,就去处理,但数据经常丢一两个字节,不知道是在加入ArrayList数组时出错,还是什么原因看看你是怎么接收数据并加到ArrayList里的我是一个字节就触发事件,然后int count =serialport.read(buffer,0,bytestoread),然后dispose(buffer)得把buffer添加到ArrayList里,收到的每个字节都要加到ArrayList,然后去分析ArrayList是的,我也是这么做的,但数据就是会丢的
找找之前的贴子呀。。
http://bbs.csdn.net/topics/390316188 字节缓冲区。。请看50楼。。