当前位置: 代码迷 >> C# >> 串口通讯SerialPort 疑义
  详细解决方案

串口通讯SerialPort 疑义

热度:749   发布时间:2016-05-05 04:04:15.0
串口通讯SerialPort 疑问!
由于工作需要,接触C#不久,做了一个串口通讯小程序。

串口通讯使用的是SerialPort,接收数据是使用SerialPort的数据接收事件。一直没什么问题,能够正常发送,接收数据。近几天发现一个比较奇怪的现象,如下:

正常通讯情况:
上位机向下位机发送数据,下位机应答返回带有8个字节信息的数据,通讯结束。

异常情况: 
上位机向下位机发送数据,下位机应答返回带有8个字节信息的数据,数据接收完,之后当这8个字节的数据中只要存在 十六进制的1A,就又会进入到SerialPort的数据接收事件中,但没有任何数据,也就是说数据长度为0,之后结束通讯。

一开始,我以为下位机又发起了串口通讯,但是经过下位机开发人员说,下位机什么都没有发,问题还是出在上位机,我就有点整不明白了,是什么触发的SerialPort的数据接收事件?为什么除了1A之外都没有问题,难道1A在SerialPort中有什么说法?


------解决思路----------------------
是什么触发的SerialPort的数据接收事件?

->
只要 “缓冲区” 有数据进来,就会触发事件。      这跟你的字节是什么 没有关系。
------解决思路----------------------
http://bbs.csdn.net/topics/70359180
http://www.dzsc.com/dzbbs/20061205/20076521157890985.html
都不了了之
其他相关查询 http://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&tn=baidu&wd=%E4%B8%B2%E5%8F%A3%E9%80%9A%E8%AE%AF%E4%B8%AD%E7%9A%840x1A&rsv_pq=fa5ca1fb00004153&rsv_t=06cdf52dIFZh4C8VkKP1a4qkEOl2Sm9MRszF2ib55CIavgkYsZxb6nuECYY&rsv_enter=1&rsv_sug3=3&rsv_sug1=1&rsv_sug2=0&rsp=0&inputT=4160&rsv_sug4=6779&rsv_sug=1

与 CTRL+Z 相关的查询 http://www.baidu.com/s?ie=UTF-8&wd=Ctrl%2Bz
------解决思路----------------------
看了里面的原码

引用:
Quote: 引用:

Quote: 引用:

再有,SerialPort中的 数据接收事件,是否能够没有数据的被触发?
也就是说,字节个数为0,的情况下,能否被触发,被谁触发?


明白你的意思了,
不过有个疑问
如果你收到的像 0x11,0x11,0x12,0x1A,0x13,0x14,0x15
这样的0x1A 按你所说的接收事件,收到0x11,0x11,0x12,0x1A 后 接收收到一个0长度的字节?后面的,0x13,0x14,0x15 还会不会继续收?


我目前状况是,你发送的0x11到0x15我都收了,这个作为正常的下位机回应。按理说,正常通讯就此结束。意外的是数据中存在0x1A时,上位机发送,下位机正常回应(0x11到0x15),我也都收了,处理了。之后莫名的就又触发了一次 数据接收事件,这次事件的触发,没有任何数据,缓冲区数据长度为0。


细看了他的原码 0x1A按你上面说的他是做为一个结束符来用, 当收到结束符后他会触发一次DataRecived事件,但里面的事件参数类型变成成 e.EventType= SerialData.Eof ,正常情况下是  SerialData.Chars。所以你应可以根据这个参数来识别是否为正常接收数据吧。
------解决思路----------------------
每当信息中有EOF就会立刻(或者说“额外”)触发事件,它原本就是这样设计的。

https://msdn.microsoft.com/zh-cn/library/system.io.ports.serialport.receivedbytesthreshold(v=vs.100).aspx

msdn上已经写明了,此事件触发“与内部输入缓冲区中的字节数无关”。
------解决思路----------------------
引用:
再有,SerialPort中的 数据接收事件,是否能够没有数据的被触发?
也就是说,字节个数为0,的情况下,能否被触发,被谁触发?


只要是曾经接收过 1A,一定会在windows消息泵中排队插入一个“接收消息”。当主线程空闲时,也就是可能恰好你已经取走了缓冲区中的数据之后,这个事件才触发。

基本上按照比较“保险、正规”的方式来编程,就不会有问题。当这个事件触发时,缓冲区里可以有0个或者多个字节,可能是 EOF 结尾也可能不是以它结尾的(在EOF之后立刻收到更多字节到缓冲区里),都应该用同样的流程来处理。