SerialPort.DataReceived 接收数据延迟

weixin_38063619 2019-04-23 08:41:24
    大家好,我在windows 7 .net framework 4.0 框架下编写的串口通讯程序,接收到数据延迟。源码如下:
      
using System;
using System.IO.Ports;
using System.Linq;
using Common.Log;

namespace Common.SerialComm
{
/// <summary>
/// 串口服务的抽象类
/// </summary>
public abstract class SerialPortCommunication
{
/// <summary>
///串口
/// </summary>
private ExSerialPort _serialProt = null;

/// <summary>
/// 通讯的锁
/// </summary>
private readonly object _commLocker = new object();

#region 属性

/// <summary>
/// 串口是否被打开
/// </summary>
public bool IsOpen
{
get
{
lock (_commLocker)
{
if (_serialProt == null)
{
return false;
}

return _serialProt.IsOpen;
}
}
}

/// <summary>
/// 波特率
/// </summary>
public int BaudRate
{
get;
private set;
}

public string Port
{
get;
private set;
}

#endregion

#region 公有方法

public SerialPortCommunication(string port, int baudRate)
{
this.Port = port;
this.BaudRate = baudRate;
}

/// <summary>
/// 开启服务监听
/// </summary>
/// <param name="port"></param>
/// <returns></returns>
public virtual bool StartService()
{
lock (_commLocker)
{
try
{
if (string.IsNullOrEmpty(this.Port))
{
return false;
}

string[] arrNames = SerialPort.GetPortNames();
string find = arrNames.FirstOrDefault(obj => obj.ToUpper().Equals(this.Port.ToUpper()));
if (find != null)
{
_serialProt = new ExSerialPort(this.Port);
_serialProt.Parity = Parity.None;
_serialProt.StopBits = StopBits.One;
_serialProt.BaudRate = BaudRate;
_serialProt.WriteTimeout = 500;
_serialProt.ReadTimeout = 500;
_serialProt.DataReceived += SerialProt_DataReceived;
_serialProt.Open();

LogHelper.Info("打开串口" + this.Port.ToString() + "成功");
return true;
}
}
catch (Exception ex)
{
_serialProt.Destroy();
_serialProt = null;
LogHelper.Info("打开串口" + this.Port.ToString() + "失败", ex);
}
return false;
}
}

/// <summary>
/// 停止服务
/// </summary>
public virtual void StopService()
{
try
{
lock (_commLocker)
{
if (_serialProt != null)
{
_serialProt.Destroy();
LogHelper.Info("关闭串口" + _serialProt.PortName.ToString() + "成功");
_serialProt = null;
}
}
}
catch (Exception ex)
{
LogHelper.Error("串口关闭失败", ex);
}
}

/// <summary>
/// 发送消息
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public bool SendMessage(byte[] message, int length = 0)
{
try
{
lock (_commLocker)
{
if (_serialProt == null || !_serialProt.IsOpen)
{
return false;
}

if (length == 0)
{
_serialProt.Write(message, 0, message.Length);
}
else
{
_serialProt.Write(message, 0, length);
}
return true;
}
}
catch
{
}
return false;
}

#endregion

protected virtual void OnReceiveMessage(byte[] bytes)
{
}

private void SerialProt_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
lock (_commLocker)
{
int byteCount = _serialProt.BytesToRead;
byte[] receiveByte = new byte[byteCount];
_serialProt.Read(receiveByte, 0, byteCount);
_serialProt.DiscardOutBuffer();
if (receiveByte != null && receiveByte.Length > 0)
{
OnReceiveMessage(receiveByte);
}
}
}
catch (Exception ex)
{
LogHelper.Fatal(string.Format("{0}接收数据异常", _serialProt.PortName), ex);
}
}
}

下面是用accessport抓包工具抓取的延迟数据
76298 下午 4:56:16.812 0.00002717 Robot.Server.e IOCTL_SERIAL_PURGE COM9 SUCCESS Purge: TXABORT TXCLEAR
76299 下午 4:56:16.872 0.00018233 Robot.Server.e IRP_MJ_WRITE COM9 SUCCESS Length: 11, Data: AA 55 CC 81 03 00 85 00 03 0B E2
76300 下午 4:56:16.875 0.33578993 Robot.Server.e IOCTL_SERIAL_WAIT_ON_MASK COM9 SUCCESS
76301 下午 4:56:17.206 0.00019561 Robot.Server.e IRP_MJ_WRITE COM9 SUCCESS Length: 22, Data: AA 55 CC 81 10 00 01 00 05 0A 64 00 01 00 00 00 00 00 00 00 E3 76
76302 下午 4:56:17.211 0.30367487 Robot.Server.e IOCTL_SERIAL_WAIT_ON_MASK COM9 SUCCESS
76303 下午 4:56:17.508 0.00018172 Robot.Server.e IRP_MJ_WRITE COM9 SUCCESS Length: 11, Data: AA 55 CC 81 03 00 85 00 03 0B E2
76304 下午 4:56:17.515 0.20769979 Robot.Server.e IOCTL_SERIAL_WAIT_ON_MASK COM9 SUCCESS
76305 下午 4:56:17.707 0.00006943 Robot.Server.e IRP_MJ_READ COM9 SUCCESS Length: 39, Data: AA 55 CC 81 03 06 08 00 74 2B 77 6D CC 1E AA 55 CC 81 10 00 01 00 05 4E 0A AA 55 CC 81 03 06 08 00 74 2B 77 6B 4C 1C
76306 下午 4:56:17.707 0.00002294 Robot.Server.e IOCTL_SERIAL_PURGE COM9 SUCCESS Purge: TXABORT TXCLEAR
76307 下午 4:56:17.710 0.00016905 Robot.Server.e IRP_MJ_WRITE COM9 SUCCESS Length: 11, Data: AA 55 CC 82 03 00 00 00 02 DB F8
76308 下午 4:56:17.723 0.04780491 Robot.Server.e IOCTL_SERIAL_WAIT_ON_MASK COM9 SUCCESS
76309 下午 4:56:17.723 0.00005675 Robot.Server.e IRP_MJ_READ COM9 SUCCESS Length: 12, Data: AA 55 CC 82 03 04 00 1E 00 20 29 25
76310 下午 4:56:17.724 0.00003381 Robot.Server.e IOCTL_SERIAL_PURGE COM9 SUCCESS Purge: TXABORT TXCLEAR



求各位大神指点方向。
...全文
200 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_38112544 2019-04-28
  • 打赏
  • 举报
回复
个人感觉和串口硬件设备的性能与传输距离有关。
但是超时300ms都没接收到硬件可能有问题,以前我使用串口通讯一般性近距离20ms-100ms延迟,中远距离200ms以内。
weixin_38103381 2019-04-24
  • 打赏
  • 举报
回复
出现的概率很低, 测试结果:几个小时出现一次延迟。我先试一下你的方案排查一下,谢谢了。
weixin_38096807 2019-04-24
  • 打赏
  • 举报
回复

Hi  tanghl,

>>谢谢你的回复, 我的实现跟你的思路是一样的。我遇到的问题是: 发送一条指令,超时300ms,没收到; 再发一条指令,超时300ms,还没收到;再发一条指令, 收到了3条回复指令。这会不会跟串口驱动的缓存区有关或跟电脑的稳定性有关。

你的这个现象就比较奇怪了。这个你需要检查下你的串口设备,你连接的设备是否按照你的指令正确上传。 首先排除你的程序问题,你可以使用串口模拟器来测试。 然后排查连接你串口设备的问题。

下面的博客可能对你有些帮助。

C#串口介绍以及简单串口通信程序设计实现

C#串口通信数据不完整

C# 解决串口接收数据不完整


Note: This response contains a reference to a third party World Wide Web site. Microsoft is providing this information as a convenience to you. Microsoft does not control these sites and has not tested any software or information found on these sites; therefore,
Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there. There are inherent dangers in the use of any software found on the Internet, and Microsoft cautions you to make sure that you
completely understand the risk before retrieving any software from the Internet. 


Best Regards

Yong Lu
weixin_38091562 2019-04-24
  • 打赏
  • 举报
回复
谢谢你的回复, 我的实现跟你的思路是一样的。我遇到的问题是: 发送一条指令,超时300ms,没收到; 再发一条指令,超时300ms,还没收到;再发一条指令, 收到了3条回复指令。这会不会跟串口驱动的缓存区有关或跟电脑的稳定性有关。
weixin_38079247 2019-04-23
  • 打赏
  • 举报
回复
串口在实际使用中如果想一次性接收完整的一条信息的几率并不大。
如果你是发送一次 然后想要接收一个数据的话,最粗暴的方式就是sleep一段时间再接收。
如果单纯的要接收完整数据的话,需要自己对每次接收的数据进行二次处理,判断接收数据包的头和尾
大概思路是,接收,寻找包头,找到后寻找包尾,将头尾数据拿走,将剩余的数据与下一次接收的数据拼接,然后再寻找包头

433

社区成员

发帖
与我相关
我的任务
社区描述
其他技术讨论专区
其他 技术论坛(原bbs)
社区管理员
  • 其他技术讨论专区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧