【问题标题】:C# Serial Port Conditional & Partial ReadingC# 串口条件和部分读取
【发布时间】:2015-10-27 15:18:56
【问题描述】:

我被难住了。脸色发青——不行。

我正在尝试与一个设备建立串行通信,该设备每 1 秒连续发送 2 个不同的数据块(一个接一个)。第一个块以“PID”开头,第二个块以“H18”结尾。

我只需要每 5 秒阅读一次。

我的问题有两个:

  1. 我不知道/控制什么时候开始读取并且经常在块中间开始。
  2. 我无法控制开始和结束周期,以确保我获得完整的两个块,因为我需要两个块。

两个块总共大约 200 个字符,开头没有 /r,各个项目之间有 /r/n。

我已尝试进行两次后续读取,但均未成功。尝试使用 StartsWith 和 EndsWith 进行游戏,但无法识别?代码已经遍布整个节目,但这里是我目前工作的基础:

static void DataReceivedHandlerbat(object sender,     SerialDataReceivedEventArgs e)
    {
        var batm = sender as SerialPort;
        if ((batm != null) && (!_gotResponse))
        {
         while (stringb.Length < 200)
            {
                byte[] buffer = new byte[batm.BytesToRead];
                int numRead = batm.Read(buffer, 0, buffer.Length);
                stringb.Append(System.Text.Encoding.ASCII.GetString(buffer));

               // if (stringb.S  == 0)
                //{
                  //   _gotResponse = true;
                    // break;
                //}
              }
         }
    }

 /// Obtain Battery string

            SerialPort batm = new SerialPort();
            batm.PortName = "com4";
            batm.BaudRate = 19200;
            batm.DataBits = 8;
            batm.Parity = Parity.None;
            batm.StopBits = StopBits.One;

            batm.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandlerbat);

            batm.Open();

            //batm.ReadExisting();

            int timeoutMsb;
            timeoutMsb = 1000;

            var startTimeb = DateTime.Now;
            while (!_gotResponse && ((DateTime.Now - startTimeb).TotalMilliseconds < timeoutMsb))
            {
                Thread.Sleep(20);
            }

            batm.Close();

            _gotResponse = false;

            //Build Battery String

            String bat = stringb.ToString();

请帮助我 - 我对 C# 还很陌生,并且为此苦苦挣扎了 4 天?

【问题讨论】:

    标签: c# .net serial-port


    【解决方案1】:

    这是一个 GUI 应用程序还是一个后台服务?无论哪种方式,放弃DataReceived 事件并使用ReadAsync,正如我展示的in my blog post。然后,将所有传入的数据缓存到List&lt;byte&gt; 中(这很容易处理分成两部分到达的消息),并实现一些同步逻辑。

    以下是同步工作原理的概述:

    1. 循环遍历List&lt;byte&gt;,找到消息的开头
    2. 确定是否已收到整条消息
    3. 复制消息有效负载并触发事件,以便作用于消息的业务逻辑可以与缓冲/解析逻辑分开
    4. 从列表中删除字节直到检测到的消息的末尾
    5. 在缓冲区的剩余部分中搜索更多有效消息(重复 1-4)
    6. 当缓冲区List&lt;byte&gt;不包含完整的消息时,再次调用ReadAsync

    【讨论】:

    • 嗨,Ben,您的博文实际上是我在发布之前在搜索中发现的内容。您的回答非常有道理,但是对于像我这样的傻瓜来说,很难复制/编码。我可以大胆地要求一些代码帮助吗?这是一个 GUI 应用程序,如上所述读取数据,将其分解为列表并解析数据并最终发布到 SQL db 后以 win 表单显示。
    • @edmundp:只需逐步构建即可。首先,创建一个循环调用await sport.BaseStream.ReadAsync()async 函数,每次获取数据时,将其写入调试控制台。请务必使用从ReadAsync 返回的实际读取的字节数,而不是完整的数组大小!然后,将缓冲添加到 List&lt;byte&gt; 并将缓冲区大小打印到调试控制台。之后,开始寻找\r\n 序列,将其前面的消息拉入一个数组(List 的CopyTo 很有帮助),将其打印到调试控制台,然后使用RemoveRange 将其从缓冲区中取出。
    猜你喜欢
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 2014-02-28
    相关资源
    最近更新 更多