//  昨天的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);      // 显示所有信息

解决方案 »

  1.   

    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("\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;
                    }
      

  2.   


    我们没有校验,只有数据包头和包尾,而且某一种指令得到的数据长度一定的(有很多指令,数据长度不一),每次都我都是把数据放到ArrayList数组中,先找头,然后找尾,如果找到了,就去处理,但数据经常丢一两个字节,不知道是在加入ArrayList数组时出错,还是什么原因
      

  3.   


    我们没有校验,只有数据包头和包尾,而且某一种指令得到的数据长度一定的(有很多指令,数据长度不一),每次都我都是把数据放到ArrayList数组中,先找头,然后找尾,如果找到了,就去处理,但数据经常丢一两个字节,不知道是在加入ArrayList数组时出错,还是什么原因看看你是怎么接收数据并加到ArrayList里的
      

  4.   

    我刚开始也是用的DataReceived事件和Threshold来设置阈值,但是DataReceived事件貌似是新开线程,我使用的总是会出现丢失字节的现象。后来我该用查询的方式,定个timer进行读取,读取里面的数据,判断数据。你可以试试
      

  5.   


    我是接过来后,放在arrlist中,然后判断,如果没达到要求,先是等待继续往arrlist中添加,最后如果数据不对,就会重发指令,目前经常会出现数据读不完,原因还在查找
      

  6.   


    我们没有校验,只有数据包头和包尾,而且某一种指令得到的数据长度一定的(有很多指令,数据长度不一),每次都我都是把数据放到ArrayList数组中,先找头,然后找尾,如果找到了,就去处理,但数据经常丢一两个字节,不知道是在加入ArrayList数组时出错,还是什么原因看看你是怎么接收数据并加到ArrayList里的我是一个字节就触发事件,然后int count =serialport.read(buffer,0,bytestoread),然后dispose(buffer)
      

  7.   


    我是接过来后,放在arrlist中,然后判断,如果没达到要求,先是等待继续往arrlist中添加,最后如果数据不对,就会重发指令,目前经常会出现数据读不完,原因还在查找
    建议是定义一个大一点的byte数组,接收到数据就往里面写,然后你再到byte数组里面去查找和做一些处理,处理完一个完整包就把那部分从byte数组里面移除
      

  8.   


    我们没有校验,只有数据包头和包尾,而且某一种指令得到的数据长度一定的(有很多指令,数据长度不一),每次都我都是把数据放到ArrayList数组中,先找头,然后找尾,如果找到了,就去处理,但数据经常丢一两个字节,不知道是在加入ArrayList数组时出错,还是什么原因看看你是怎么接收数据并加到ArrayList里的我是一个字节就触发事件,然后int count =serialport.read(buffer,0,bytestoread),然后dispose(buffer)得把buffer添加到ArrayList里,收到的每个字节都要加到ArrayList,然后去分析ArrayList
      

  9.   


    我们没有校验,只有数据包头和包尾,而且某一种指令得到的数据长度一定的(有很多指令,数据长度不一),每次都我都是把数据放到ArrayList数组中,先找头,然后找尾,如果找到了,就去处理,但数据经常丢一两个字节,不知道是在加入ArrayList数组时出错,还是什么原因看看你是怎么接收数据并加到ArrayList里的我是一个字节就触发事件,然后int count =serialport.read(buffer,0,bytestoread),然后dispose(buffer)得把buffer添加到ArrayList里,收到的每个字节都要加到ArrayList,然后去分析ArrayList是的,我也是这么做的,但数据就是会丢的
      

  10.   


    找找之前的贴子呀。。
    http://bbs.csdn.net/topics/390316188 字节缓冲区。。请看50楼。。
      

  11.   

    试一试把上位机程序的串口的DTR和RTS打开,再看一下还有没有丢数据情况