如何通过串行连接有效地使用设备?

时间:2009-12-08 20:27:33

标签: .net .net-3.5 serial-port

我很长时间都在努力解决这个问题,我确实得到了一个最终解决方案,但它并不漂亮,我希望从stackoverflow社区获得一些关于如何做到这一点的智慧。

基本上我正在使用菊花链式连接到计算机的电机,我必须使用.Net中的SerialPort类与它们通信,它通过计算机上安装的一些驱动程序通过USB与电机通信

问题是电机是菊花链式的,当我问

从一个人那里得到信息,或者告诉它做某事,我必须等待结果回来之后再用那个马达或其他任何一个做其他事情。

我刚刚度过了一段艰难的时光,而且我确信有更好的方法来处理我从未接触过的串行通信。对于这类事情,是否有任何良好的指导方针或最佳做法?这是一个相当标准的事情(串行通信 - 通过安装在计算机上的驱动程序> usb)

我正在使用MDrive23Plus Motion Control中的六个IMS电机。

我可以提供更多细节,但我不确定这会导致什么。我希望这对StackOverflow来说足够具体,尽管我知道它有点模糊。我真的不知道如何更好地问它。

真正归结为如何有效地同步通信,以及如何有效地等待和读取有效的数据?我知道这对某些人来说可能很简单,但它对我来说效果不佳。

5 个答案:

答案 0 :(得分:2)

这是工作多点串口网络的极限.....它没有魔力,你可以缓解一些痛苦

一般来说,最好的方法是在一个抽象层中放置一个你要发送的事物的消息队列,并且每个都有一个回调,当它得到响应时会被调用。

答案 1 :(得分:1)

您可能需要多个线程和/或异步操作。在过去,当进行串行通信(不是在.NET中)时,我们会在端口上排队读取。当读取完成时,回调函数(委托)将触发,将执行读取处理,可能改变控制状态 - 我们的典型示例是条形码读取,同时具有键盘读取和计时器。其中一个事件将完成,这将导致一个动作(可能会留下其他排队的读取或取消它们,具体取决于状态转移到哪里。)

您可能希望研究使用状态机。在这种情况下,状态机知道正在进行的操作,允许哪些转换以及如何在它们之间进行转换以及转换导致的操作。

答案 2 :(得分:1)

我为Zaber Technologies工作,我为精密步进电机控制器构建了一个控制库,通过菊花链式串行连接进行通信。我使用了三层:

  1. 端口 - 该层只关注通信协议。它公开了发送消息的方法,并将消息参数转换为字节流。它还会侦听传入的线路,将字节流转换为消息结构,并在收到完整的消息时引发事件。
  2. 设备 - 该层知道如何将消息发送到菊花链中的特定设备,以及如何过滤掉菊花链中其他设备的响应。
  3. 对话 - 此层协调请求和响应,并允许调用代码发出阻止线程的请求,直到响应返回。
  4. 然后,调用代码可以选择是否对会话层使用同步请求,或者对设备层使用异步请求。

    如果您对更多详细信息感兴趣,可以下载the source code或查看有关针对该库编写脚本的user documentation

答案 3 :(得分:1)

许多设备在其串行通信上变幻无常。有些设备的通信在其指定的波特率读取行时无法正常工作。

我发现我必须描述设备的通信特征。有些供应商的同一型号的两个设备的通信特性不同。表征是一个相当乏味的事情。表征包括发现各种情况的组合,然后考虑可能性。

  1. 插入延迟之前连续读取/写入的最低阈值字节数。可能性是一次一个角色。
  2. 恢复读/写之前最安全的最短延迟。
  3. 从初始化通信到稳态通信所需的最小延迟的变化。
  4. 在插入延迟之前,在指定波特率下可写入的阈值字节数的变化。
  5. 最糟糕的情况是影响读/写操作清洁度的状态/组合可能性增加,并且通过在使用读/写操作组之间使用最慢的公分母来减少状态数。必须有一个科学背后的所有这些,但我只是尝试使用蛮力测试我的伏笔。

    当然,这会导致读/写层将需要通信的例程与直接与端口通信分开。

    或者,我们都知道快速和懒惰但效率低的方法是在每个字节后插入10毫秒等待。

答案 4 :(得分:1)

我自2004年以来一直在使用.net串口类,我同意状态机可能就是这里的方式,一起发送命令,然后等待握手中的相关响应(设备将在响应时它准备回应了。)

将您的serialPort.DataReceived()事件处理程序视为您的前端。 然后让DataReceivedBeginInvoke()而不是Invoke(),因为串口是方法的异步接口,AddReceive() 接下来,在AddReceive()中计算它看到的字节数 如果大于0,则将数据附加到stringbuilder容器,比如说sbReceived 最后激活一个计时器处理程序来拾取流中的任何“遗留”数据,它还对方法ReadData()执行'beginInvoke' 现在我们准备解析数据并传递给终端显示器(这里最好使用richtext框),颜色代码各种提示指示>>输出数据,<<在数据,配置,错误,状态 由于每个端口都有各种端口可供监控和i / o状态,因此可以在一个终端显示器内完成。

我同意状态机在这里是好主意,反正过程非常有状态;在等待其他端口上发送串口命令之前,您正在等待serial1解析输出的输出以匹配您所需的输出。这样做可以保持组织有序,并且可以很好地分割出不同的串口活动。在另一种情况下,您可能会发生多个后续命令/查询输出和设备响应周期,最好在两者之间执行while(serial1.ByteCount==0){};,让设备控制握手中响应的时间。将调试数字I / O设备连接起来也很有帮助,这样您就可以切换线路以监控延迟时间,并观察DSO以验证是否满足时序要求。

最后,确保在每个写/读周期清除端口,这样就不会出现溢出问题,同时重新初始化数据缓冲区,字符串生成器容器等。

度过美好的一天