日期:2014-05-19  浏览次数:21729 次

用SerialPort类做串口通信,为什么发送一次数据有时接收方要收两次?
用SerialPort类做的一个串口通信的测试程序,添加了DataReceived事件处理方法,用两台机器串口直接对联发送数据,发送方在发送多于8个字节的数据时,接收方有时要分两次收,而且每次第一次收都是8个字节,这是为什么?
接收发送时都做了数据转换,发送时将string转换为byte数据发送,接收方也以byte类型接收,再转换成string类型显示,如果不转换发送中文时出错!

------解决方案--------------------
检查一下Rthreshold属性和inbuffersize属性
------解决方案--------------------
对呀,我虽然不是做的串口通信,我做的是socket通信,跟你你样的问题,不过我是这样解决的
len是我接收到的(可能是第一次接受到的)
packlen是我发过来的一个包的大小
while (len < packlen)
{
int TcpFile = cs.ClientSocket.Receive(cs.buff, 0, cs.buff.Length - len, SocketFlags.None);
len += TcpFile;//便于while做出正确判断
}
如果我接受的数据小与一个包的大小,我就再去Receive一次
------解决方案--------------------
串口通信和socket通信貌似还是有差别的
------解决方案--------------------
myup5201314() 正解。

你不能假定,一次发送,就能一次接收。

电脑串口通讯,我们唯一可以确认的就是,接收不会切断字节,也就是接收只发生在字节边界处,所以,我们通常在第一个字节指示发送包的长度。

实际上,早期的单片机接收缓冲区只有4个bit,接收就会发生在4个位处,现在通常缓冲区8个位。

对于PC来说,这个缓冲区还可以更大。

串口通讯是不可靠的,第一个字节有可能丢失,造成接收异常,有时候单片机速度慢还会不能及时响应造成缓冲区溢出,结果后面发送的会冲掉前面发送的内容。这时候我们需要使用串口的控制线来进行同步。

如果使用控制线,可以不需要长度,也不需要其他额外的校验,当然也可以进行一定的校验。在发送数据的时候,你可以让某个控制线始终处于高电平,当发送结束时,控制他为低电平。

此外还需要缓冲区的高低电平控制,缓冲区满时拉高某个控制线的电平。

对于PC来说,这些其实可以省略,PC对PC可以保证缓冲区不溢出。还可以保证接收的数据完整。

你要做的,就是使用2根空闲的控制线来同步两者间数据发送。
------解决方案--------------------
检查一下Rthreshold属性和inbuffersize属性
正解
------解决方案--------------------
如果不使用控制线,那么就需要在第一个字节指出数据包长度。

还可以使用启停标志的办法,你可以用一个特殊的字符表示数据包开始或者结束。

但是,串口通讯是如此的不可靠,非常不可靠。你必须在你的数据包中加入一些校验信息,同时,通讯双方还必须约定错误控制机制。通常还需要一些特殊的控制字符来做这些事情。
------解决方案--------------------
串口的通讯可靠不可靠取决于环境和协议,就想同样是双绞线,用UDP协议和TCP协议传输数据可靠性是完全不一样的,串口的电气性能是没有问题的,毕竟是很成熟的技术了,并且广泛的运用在工业控制领域,所以不能说串口通讯是不可靠的。串口参数中的停止位和校验位都可以简单的纠正通讯中的错误。但楼主的问题显然不是串口不稳定造成的,若是不稳定应该产生误码才对,而不是数据流的截断!
问题的原因应该是串口配置的问题。
------解决方案--------------------
串口的握手协议主要用于接收方过载的情况
------解决方案--------------------
那个Serlai类可以设置接收到几个字节后触发那个DataReceived的事件,你可以设置接收1个字节就触发,然后可以一次性把缓冲区里面的数据全部拿出来
你最好设计一个好一点的协议,我曾经做的那个要有非常大的电流,有100安培还不止,搞得干扰很严重
------解决方案--------------------
ReceivedBytesThreshold决定接收几个字节触发DataReceived,默认为1
串口编程基本都会遇到这个问题!

我的办法:定义一个全局变量,DataReceived事件连接读到的字符串,满足条件处理完当前数据后,清空变量!

------解决方案--------------------
我也遇到类似问题,现在做法:先发送数据包长度,然后循环读取;或者发送时在最后添加结束标志,接受时一直读到结束标志为止。
------解决方案--------------------
串口是慢速通讯机制,当你的串口有数据到达,响应事件的时候,其实数据还没有发送完毕,如果你非要一次就接收完毕,你要设立一个延时

我建议你不要设立延时,而是在你的串口指令编码中设置好标志位,例如字节的起始标志和终止标志,以及字节长度等信息,通过判断这些信息达到完成接受的目的。

我做串口是采用一个死循环,一直采集,然后分割数据,把数据成块加入到ArrayList

可以看我得Blog

http://blog.csdn.net/cnming/archive/2007/05/06/1597930.aspx

串口程序不处理好,会有数据掉包的现象

------解决方案--------------------
串口(RS232)的通讯是不可靠的,他的电气特性不同于使用对绞线的网线。

1、他使用TTL电平,电压高。
2、允许的漏电流较高,容易受到干扰,也不可以长距离传送。
3、使用原始的高低电平来区别1、0,延时,码率不同都会造成干扰。

短距离,优良环境中才能可靠工作,如果在恶劣环境中,要么使用RS485,或者使用光电串口,并且加上软件纠错。

LZ的问题并非干扰,我只是告诉他,将来要注意干扰问题,在设计通讯协议的时候要充分考虑串口的不可靠。