简单的可靠通信算法

时间:2012-08-27 06:50:41

标签: serial-port communication

所以,我过去曾经在大型系统上工作过,就像iso堆栈会话层一样,这样的东西对于我需要的东西来说太大了,但我确实对大局有所了解。我现在拥有的是一个串行点对点通信链路,其中一些组件正在丢弃数据(通常)。

因此,我将不得不编写自己的,可靠的传送系统,使用它进行传输。有人可以指出我的基本算法的方向,甚至提供一个线索,他们被称为什么?我曾尝试过谷歌,但最终还是研究了遗传算法等方面的理论。我需要基础知识。例如10-20行纯C。

5 个答案:

答案 0 :(得分:1)

  1. XMODEM。它已经很老了,很糟糕,但它在硬件和软件方面得到了广泛的支持,图书馆可用于各种语言和市场领域。

  2. HDLC - 高级数据链路控制。它是在过去30年中诞生了许多可靠协议的协议,包括TCP / IP。您无法直接使用它,但它是如何开发自己的协议的模板。基本前提是:

    • 每个数据字节(或数据包)都编号为
    • 通信双方在本地维护两个号码:最后收到和最后发送
    • 每个数据包都包含两个数字的副本
    • 通过发回带有更新号码的空(或非)数据包确认每个成功传输
    • 如果在某些超时内未确认传输,请再次发送。

    对于特殊处理(同步),向数据包添加标志(通常只有一位就足够了,告诉数据包是特殊的并使用)。不要忘记CRC。


  3. 这两种协议都没有任何类型的会话支持。但是你可以通过简单地添加另一个层来引入一个 - 一个简单的状态机和一个计时器:

    • 会话以特殊数据包开始
    • 在指定的超时时间内应该至少有一个(可能是空的)数据包
    • 如果此方未在超时/ 2内发送数据包,则发送空数据包
    • 如果在超时内没有从通信的另一端看到数据包,则会话已被终止
    • 可以使用另一个特殊数据包进行正常会话终止

    这就像会话控制一样简单。

答案 1 :(得分:0)

这个问题有(IMO)两个方面。

首先,如果数据被丢弃,那么我会首先考虑解决硬件​​问题,否则您将拥有GIGO

至于通信协议,您的帖子建议一个相当简单的系统?您想要验证数据(奇偶校验,sumcheck?)还是想要包含纠错?

如果只需要验证,我就可以使用RS232和CRC8 sumchecks运行可靠的系统 - 在这种情况下this StackOverflow page可能有帮助

答案 2 :(得分:0)

如果某些组件在串行点对点链接中丢弃数据,则代码中必定存在一些错误。

首先,您应该确认物理层的通信没有问题

其次,你需要一些关于数据通信理论的知识,比如ARQ(自动请求重传)

答案 3 :(得分:0)

进一步的想法,在考虑了你对前两个答案的回答之后......这确实表明了硬件问题,而且没有多少聪明的代码可以解决这个问题。

我建议你在链路上安装示波器,这有助于确定故障的位置。特别要看一下双方的波特率(Tx,Rx)以确保它们在规范内......自动波特率通常是个问题?!

但是看看辍学是否有规律,或者可以与任何其他活动同步。

答案 4 :(得分:0)

发送方;

/////////////////////////////////////////  XBee logging
void dataLog(int idx, int t, float f)
{
    ubyte stx[2] = { 0x10, 0x02 };
    ubyte etx[2] = { 0x10, 0x03 };

    nxtWriteRawHS(stx, 2, 1);
    wait1Msec(1);

    nxtWriteRawHS(idx, 2, 1);
    wait1Msec(1);

    nxtWriteRawHS(t, 2, 1);
    wait1Msec(1);

    nxtWriteRawHS(f, 4, 1);
    wait1Msec(1);

    nxtWriteRawHS(etx, 2, 1);
    wait1Msec(1);
}

在接收方

void XBeeMonitorTask()
        {
            int[] lastTick = Enumerable.Repeat<int>(int.MaxValue, 10).ToArray();
            int[] wrapCounter = new int[10];


            while (!XBeeMonitorEnd)
            {
                if (XBee != null && XBee.BytesToRead >= expectedMessageSize)
                {
                    // read a data element, parse, add it to collection, see above for message format
                    if (XBee.BaseStream.Read(XBeeIncoming, 0, expectedMessageSize) != expectedMessageSize)
                        throw new InvalidProgramException();

                    //System.Diagnostics.Trace.WriteLine(BitConverter.ToString(XBeeIncoming, 0, expectedMessageSize));

                    if ((XBeeIncoming[0] != 0x10 && XBeeIncoming[1] != 0x02) ||  // dle stx
                        (XBeeIncoming[10] != 0x10 && XBeeIncoming[11] != 0x03))   // dle etx
                    {
                        System.Diagnostics.Trace.WriteLine("recover sync");
                        while (true)
                        {
                            int b = XBee.BaseStream.ReadByte();
                            if (b == 0x10)
                            {
                                int c = XBee.BaseStream.ReadByte();
                                if (c == 0x03)
                                    break;     // realigned (maybe)
                            }
                        }
                        continue;   // resume at loop start
                    }

                    UInt16 idx = BitConverter.ToUInt16(XBeeIncoming, 2);
                    UInt16 tick = BitConverter.ToUInt16(XBeeIncoming, 4);
                    Single val = BitConverter.ToSingle(XBeeIncoming, 6);

                    if (tick < lastTick[idx])
                        wrapCounter[idx]++;
                    lastTick[idx] = tick;

                    Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => DataAdd(idx, tick * wrapCounter[idx], val)));
                }
                Thread.Sleep(2);  // surely we can up with the NXT
            }
        }