如何以面向对象的形式实现串行通信协议?

时间:2010-11-30 12:57:45

标签: delphi oop communication

我正在使用通过RS232连接到PC的嵌入式设备。

我需要做一个软件来与这个嵌入式设备进行通信。

我在Delphi中编程。我以前从未习惯使用面向对象。但我想改变这一点。

我无法以面向对象的方式思考解决这个问题。

我有这个协议:

<STX><STX><COMMAND>[<DATA><DATA>...]<CHKSUM><ETX>

其中:

<STX> is the Start of TeXt (0x55);
<COMMAND> can be 0x01 for read, 0x02 for write, etc;
<DATA> is any value;
<CHKSUM> is the checksum;
<ETX> is the End of TeXt (0x04).

软件计算机将通过串口发送命令,设备将使用相同的协议应答。

例如:

Reset command
PC sends     : <STX><STX><0x09><0x00><CHKSUM><ETX>
Device answer: <STX><STX><0x09><0x00><CHKSUM><ETX>

Get Version
PC sends     : <STX><STX><0x00><0x02><CHKSUM><ETX>
Device answer: <STX><STX><0x00><0x00><VER_L><VER_H><CHKSUM><ETX>

我必须将文件流发送到设备。

我想获得以面向对象的方式实现这一点的最佳方法的建议和/或示例。我也希望能够进行单元测试。

由于

3 个答案:

答案 0 :(得分:4)

您应该查看其他串行发送/接收通信模型,例如HTTP。在.NET中,HTTPWebRequest对象是您将通过线路发送的所有信息收集在一起的地方 - 包括命令(HTTP METHOD:GET,PUT,POST等)和字节流。 HTTPWebRequest对象(和HTTP堆栈)在内部处理计算数据校验和的“文书工作”,将大数据分块为较小的数据包等。您的所有代码都要构造请求对象,设置命令,分配数据流到请求对象的属性,并发送。

您应该查看现有通信对象模型(如.NET HTTP)的另一个原因是,从主机CPU的角度来看,串行通信通常是异步的。在串口上传输请求的字符时,等待响应时,可以经过很多CPU时间。为请求/响应使用异步模型,这样就不会阻塞调用线程并可能冻结UI。

要继续.NET HTTP示例,HTTPWebRequest有一个GetResponse方法,该方法发送请求并阻止调用线程,直到收到响应。 HTTPWebRequest还有一个BeginGetResponse()/ EndGetResponse()对,这样您就可以发送请求并提供一个回调,以便在以后的某个时间到达时执行。

即使您的直接设计可以使用线程阻塞同步调用模型,您至少应该研究异步编码模式并考虑实现您的对象。您始终可以以线程阻塞同步方式调用异步方法,但以异步方式调用同步方法要困难得多。现在投入一点时间为自己提供更多选择。

答案 1 :(得分:2)

很难回答但是从我有的少量信息来看,这就是我的方法:

要么是知道如何序列化自己的类,要么是使用访问者模式进行序列化。这样做的好处是可以将数据与序列化分离,并且可以更轻松地实现其他序列化机制。

所以我有一个Data类,一个Command类,它包含一个Data的集合(选择你喜欢的容器)。 Command类可能会通过公共方法处理校验和计算。我还有一个通信类来封装Command并开始和结束通信。然后我会有一个类负责与串口连接,该串口将有一个Send方法,可以在通信类上引用。

从可用的信息来看,这就是我在设计方面的想法。

对于单元测试,如果设计合理,您应该可以对几乎所有内容进行单元测试。记得使用存根,你不想在测试期间点击那个串口,所以制作一个假的串行通信类,例如用字符串写入,并将输出的字符串与预期的值规范进行比较。

答案 2 :(得分:2)

嗯,我猜有很多解决方案和程序员一样多。如果不了解您的系统,我可能会采用这种方法:

创建一个基本命令类,让我们说; TBaseCommand。在此级别定义您的公共接口,如Send(),Receive(),Run()等...

仅填写所有命令常用功能的代码,例如发送,接收等...

将执行不同的函数设置为虚拟以在下一层中定义。 由此为每个命令派生一个新类并填写命令特定代码,例如Run()。

使用Run()可以轻松地通过覆盖Run()函数来模拟屏幕上的命令。

,并且是您的传输协议,应该由您的通信接口应用和剥离(单独的协议类?)。您的协议类也可以处理校验和错误并尝试重新发送等。如果无法解决,则发出信号错误。

这只是我头脑中的一些有限的描述......