当前位置: 代码迷 >> C# >> 急大约每50ms发一次串口数据失去的串口数据丢很多
  详细解决方案

急大约每50ms发一次串口数据失去的串口数据丢很多

热度:184   发布时间:2016-05-05 05:14:28.0
急!大约每50ms发一次串口数据得到的串口数据丢很多
串口命令是3个字节:0xF6,OxA3,Ox11,返回的内容是17个字节,头三个字节Ox28,0xAF,0x11,最后一个字节0xAF表示接收到的值是正确的,一边让电机旋转一边通过串口读取磁场的值,大约每50ms发一次命令,电机旋转2.3圈,但是收到的串口数据很少,正常的时候是100多,现在不正常的时候只有开始几个,就算是100多的也是丢很多的,因为在VC中实现相同的功能,电机旋转2.3圈收到的磁场值有200多个,VC中用的读写串口的方式,是CreateFile(),和ReadFile()的方法。C#中串口接收代码如下:注释掉的是以前的方法,现在都是用的没有注释掉的方法,我查了网上,也都是这样用缓存的方式接收的,为什么会丢这么多数据呢?

 private void MLXSerialport_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                //bufferPointerMLX = byteReadMLX;   //这种方式不够准确
                //byteReadMLX += MLXSerialport.Read(MLXReceivedArray, bufferPointerMLX, MLXReceivedArray.Length - bufferPointerMLX);
                //if (byteReadMLX == MLXReceivedArray.Length)
                //{
                //    if (MLXReceivedArray[0] == 0x28 && MLXReceivedArray[1] == 0xAF && MLXReceivedArray[2] == 0x11 && MLXReceivedArray[16] == 0xAF)
                //    {
                //        magZInfo = (MLXReceivedArray[7] & 0x3F) * 256 + MLXReceivedArray[8];
                //        if (magZInfo > (int)Math.Pow(2, 13)) magZInfo -= (int)Math.Pow(2, 14);  //大于2^13就为负值
                //        magYInfo = (MLXReceivedArray[3] & 0x3F) * 256 + MLXReceivedArray[4];
                //        if (magYInfo > (int)Math.Pow(2, 13)) magYInfo -= (int)Math.Pow(2, 14);
                //        if (autoFindMaxonHorHomeFlag) writeExceptionToLogFile("magYInfo", magYInfo.ToString());
                //    }
                //    bufferPointerMLX = 0;
                //    byteReadMLX = 0;
                //}

                int n = MLXSerialport.BytesToRead;
                byte[] actualBuf = new byte[n];
                MLXSerialport.Read(actualBuf, 0, n);
                MLXPortComBuffer.AddRange(actualBuf);  //不断累积每次到达串口的数据
                while (MLXPortComBuffer.Count >= 3)  
                {
                    if(MLXPortComBuffer[0]==0x28 && MLXPortComBuffer[1]==0xAF && MLXPortComBuffer[2]==0x11)  //帧头正确
                    {
                        if (MLXPortComBuffer.Count < 17) break;
                        MLXPortComBuffer.CopyTo(0, MLXReceivedArray, 0, 17);
                        if(MLXReceivedArray[16]==0xAF)  //帧尾正确
                        {
                            magZInfo = (MLXReceivedArray[7] & 0x3F) * 256 + MLXReceivedArray[8];
                            if (magZInfo > (int)Math.Pow(2, 13)) magZInfo -= (int)Math.Pow(2, 14);  //大于2^13就为负值
                            //if (autoFindMaxonVerHomeFlag)
                            //{
                                magZArray.Add(magZInfo);
                                int verPos = GetPulsePositionIs(MaxonBNodeId);
                                VerPosArray.Add(verPos);
                                autoFindHomeIndex++;
                            //}
                            magYInfo = (MLXReceivedArray[3] & 0x3F) * 256 + MLXReceivedArray[4];
                            if (magYInfo > (int)Math.Pow(2, 13)) magYInfo -= (int)Math.Pow(2, 14);
                            //if (autoFindMaxonHorHomeFlag) writeExceptionToLogFile("magXInfo", magYInfo.ToString());
                            //if(autoFindMaxonHorHomeFlag)
                            //{
                                magXArray.Add(magYInfo);
                                int horPos = GetPulsePositionIs(MaxonANodeId);
                                HorPosArray.Add(horPos);
                                autoFindHomeIndex++;
                            //}
                        }
                        MLXPortComBuffer.RemoveRange(0, 17);
                    }
                    else
                    {
                        MLXPortComBuffer.RemoveAt(0);
                    }
                }
            }
            catch(Exception ex)
            {
                writeExceptionToLogFile("MLXComReceive", ex.Message);
            }
        }

------解决思路----------------------
1.去掉异常处理看看
2.把你接收和处理代码分开,正常接收,用异步的方式处理你接收到的数据(或者多线程),以保证接收的通畅。

别让数据传输的速度快过你处理代码的速度
------解决思路----------------------
楼主你发的代码没有初始化串口对象的代码;

你的代码思路没太看明白。RemoveAt的代码语句逻辑正确吗,是不是应该这样,每次添加数据前,先判断来的字节头几个是不是Ox28,0xAF,0x11,是的话,清除历史数据。添加来的数据并等待下次接收;否的话,添加来的数据,做相关处理(这里可能有尾帧)。

另外,你这代码怎么没有看到委托或者其它跨线程的东西,不需要?

实在搞不清楚的话,就将接收的数据存全部储到一个载体,查看一下。
------解决思路----------------------
看了楼主的代码没发现问题= =
我处理串口数据也是类似的思路
代码别的部分有没有对串口进行处理呢?
LZ描述的还有个问题好蹊跷,在C#里跑完程序关闭用VC跑竟然也会导致异常。。。
帮顶吧
------解决思路----------------------
你这样写,非常可能会丢数据的。
         int n = MLXSerialport.BytesToRead;                 byte[] actualBuf = new byte[n];                 MLXSerialport.Read(actualBuf, 0, n); 
------解决思路----------------------
感觉累计串口数据分析后删除有错误,我一般是分析是否是开头字节,到了后根据字节编码获取值,然后循环到最后一个完成编码,把剩余部分累加到下一次,这样就不丢了!删除已经分析完了的,留下不完全数据等待下一次累加。
------解决思路----------------------
引用:
引用:看了楼主的代码没发现问题= =
我处理串口数据也是类似的思路
代码别的部分有没有对串口进行处理呢?
LZ描述的还有个问题好蹊跷,在C#里跑完程序关闭用VC跑竟然也会导致异常。。。
帮顶吧
不是接收代码里处理造成丢包,我把处理代码注释掉,把它全存在MLXPortComBuffer中,然后存在文件里,接收到的就没有多少数据,除……


把接收到的数据全部存储起来数据个数也很少吗,00也说明串口有数据的,00也要算上
------解决思路----------------------
没太看懂你的东西,具体原因大约一下几种吧:

串口缓存是多大?是不是还没把数据取走,新的数据就给覆盖了?

ReadFile取数据后是否立即处理了,还是放到链表里了?

发送和收取的定时器不要相同,最好取的要快一些,windows一般也就到15-18ms左右吧,如果不行用多媒体定时器。

另外,你可以用串口工具查看一下,数据是否发出了

------解决思路----------------------
我就一点建议,把你的处理数据的内容,放到异步进行操作,不要直接放到哪个事件里边,你试试看~
------解决思路----------------------
那如果不用定时器呢,直接开另一个线程实时返回数据
------解决思路----------------------
不处理的话能都收到吗?