在C#中重新组装串行消息

时间:2012-01-28 05:36:07

标签: c# serial-port serial-communication

我是C#和Serial通信领域的新手。阅读了一些教程,我设法让沟通工作。我问了另一个类似的问题here,但我不认为我问了正确的问题。我按照上一个问题给出的建议并稍微更改了我的代码,以便我现在从微控制器发送一条如下所示的串行消息:

SxxxxxxxxxxxxxxxxxxxxxxxxE

x表示不同的数字,加号和减号以及逗号。我发送的字符串将始终具有相同的长度,并始终以S开头并以E结尾(如果这很糟糕,我可以更改它)。我遇到的问题是,当我尝试读取串行线时,我一次只得到部分消息,所以这样的事情:

Sxxxxxxx
xxxxx
xxxxESxxx

我是从微控制器连续发送这些信息但只是想在某些时候访问它,所以换句话说我正在尝试编写一个函数来接收消息的所有部分,将它放回到gether然后返回它来自我的功能。问题是我现在不知道该怎么做。

非常感谢任何帮助!

这是我一直在玩的代码:

    SerialPort serialHC = new SerialPort(); // serial connection dealing with Hand Controller

     public string receiveCommandHC()
    {

        string messageHC = "";
        if (serialHC.IsOpen)
        {
            //serialHC.DiscardInBuffer();
            //messageHC = serialHC.ReadLine();
            messageHC = serialHC.ReadTo("*");
            //tempMsgHC = serialHC.ReadTo("*");
            //i = tempMsgHC.IndexOf("S");
            //tempMsgHC.Remove(0,i);
            //messageHC = tempMsgHC;

            //serialHC.Read(bufferHC = new byte[serialHC.BytesToRead], 0, serialHC.BytesToRead);
        }
        return messageHC;

我过去的消息结尾是“*”

刚试了一个例子here这就是我从中得到的。 Serial Message Received

这是我发送的内容(使用Putty检查) enter image description here

1 个答案:

答案 0 :(得分:2)

看起来,当您收到数据时,您无法真正采取行动。您不一定有完整的信息。因此,在检测到您有完整的消息之前,您需要缓冲所读取的内容。

可能有更有效的方法来做到这一点,但我不太熟悉它们。所以这是一个处理这个的天真算法。它可以作为一个简单的状态机实现。

初​​始化:

  1. 分配足够大的缓冲区以容纳最大的消息。这将在您读入传入数据时保留消息,直到您准备好处理它为止。

  2. 分配固定大小的缓冲区以读取数据。

  3. 输入“等待消息”状态。

  4. 等待留言:

    1. 读取每个符号,直到找到“S”或到达消息的末尾。
    2. 如果找到“S”,请输入“阅读消息”状态。
    3. 如果找不到“S”,请等待下一条消息。
    4. 阅读留言:

      1. 将数据中的每个符号复制到消息缓冲区,直到找到“E”或者到达消息的末尾。
      2. 如果找到“E”,请安排要处理的消息缓冲区的内容,清除它并输入“等待消息”状态。
      3. 如果未找到“E”,请等待下一条消息。

      4. 以下是一些捕获算法本质的代码:

        enum ReadState { Waiting, Reading, Finished }
        static string ReadMessage(SerialPort port)
        {
            var messageBuffer = new StringBuilder("S");
            var state = ReadState.Waiting;
            while (state != ReadState.Finished)
            {
                switch (state)
                {
                case ReadState.Waiting:
                    if (port.ReadChar() == 'S')
                    {
                        state = ReadState.Reading;
                    }
                    break;
                case ReadState.Reading:
                    messageBuffer.Append(port.ReadTo("E"));
                    state = ReadState.Finished;
                    break;
                }
            }
            return messageBuffer.ToString();
        }
        

        我最初在更低级别考虑这个问题,SerialPort类似乎有一些方法可以使这更容易。