昨天的comport.ReadExisting()问题困扰着我,如何读取到完整的PLC代码呢?今天终于解决了。我的思路还是对着的,不停地读取缓冲区的数据,直到把完整的代码读完。但是忽略了port_StringDataReceived时间的触发问题,再找到ReceivedBytesThreshold关键词后进行了搜索,理解了port_StringDataReceived事件的控制,然后就是写不停地读取缓冲区的数据,直到把完整的代码读完的算法,这里要说的是,半路出家很多细节问题要解决,我刚开始只是注意功能的实现,没有注意捕捉程序异常,处理异常,使得程序不能完整的运行。再经历了一上午的努力终于实现了数据的监测,就是速率有点慢。这都是单线程惹的祸,看来还得学习一下后台线程的使用。
下面是我的代码,这里要感谢SCDN论坛的 Yali8 网友,他的算法的完整性很高,我在他的基础上进行了修改,得到了我想要的代码。还要感谢网友 剑客QQ:316722224 ,给我的耐心解答。下面分享一下我的成果~
图1 监测效果图
ReceivedBytesThreshold只是触发DataReceived事件的一个阀值,由于串口通讯的实时性,很难说你每次读取的数据长度就是阀值的长度。请参考下面的方法。
一、技术要点:
(1).首先,SerialPort的ReceivedBytesThreshold先设置成1,表示只要有1个字符送达端口时便触发DataReceived事件
(2).当DataReceived触发时,先把ReceivedBytesThreshold设置成一个比较大的值,达到读取本次端口数据时,不再触发DataReceived.
(3).循环读取端口中的数据,直至读完。
(4).移除读取数据中的非法字符。
(5).触发一个后台线程处理收到的数据。
(6).在finally中把ReceivedBytesThreshold重置回1
二、C# Code
public void port_StringDataReceived(objectsender, SerialDataReceivedEventArgse)//接收数据,翻译为十进制数值,存储到字符串数组
{
string strReceive;
string PLCCode=null;
string[] data =null;
try
{
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(" ",string.Empty);//去除非法符号,本例可以不要。
PLCCode = PLCCode.Replace("rn", string.Empty);
PLCCode = PLCCode.Replace("r", string.Empty);
PLCCode = PLCCode.Replace("n", string.Empty);
//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(this, ex.ToString(), Application.ProductName,MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
comport.ReceivedBytesThreshold = 1;
}
//调用将代码翻译为数据的子程序,返回值为带符号十进制整数
if (PLCCode.Length == 25)
{
data = PLCCodeToStringData(PLCCode);
string LWA = data[0];
string RWA = data[1];
LogMonitoringPage(LWA,RWA);// 显示有效信息到监测界面
}
Log(LogMsgType.Incoming,PLCCode);// 显示所有信息