串口命令是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);
------解决思路----------------------
感觉累计串口数据分析后删除有错误,我一般是分析是否是开头字节,到了后根据字节编码获取值,然后循环到最后一个完成编码,把剩余部分累加到下一次,这样就不丢了!删除已经分析完了的,留下不完全数据等待下一次累加。
------解决思路----------------------
把接收到的数据全部存储起来数据个数也很少吗,00也说明串口有数据的,00也要算上
------解决思路----------------------
没太看懂你的东西,具体原因大约一下几种吧:
串口缓存是多大?是不是还没把数据取走,新的数据就给覆盖了?
ReadFile取数据后是否立即处理了,还是放到链表里了?
发送和收取的定时器不要相同,最好取的要快一些,windows一般也就到15-18ms左右吧,如果不行用多媒体定时器。
另外,你可以用串口工具查看一下,数据是否发出了
------解决思路----------------------
我就一点建议,把你的处理数据的内容,放到异步进行操作,不要直接放到哪个事件里边,你试试看~
------解决思路----------------------
那如果不用定时器呢,直接开另一个线程实时返回数据
------解决思路----------------------
不处理的话能都收到吗?