【问题标题】:Reading from serial port affecting values从串口读取影响值
【发布时间】:2013-09-09 12:31:26
【问题描述】:

我在尝试正确阅读 SerialPort 类时有点头疼。

如果我使用阻塞方法ReadLineReadExisting,应用程序就像魅力一样,但我的一些值会因为string 转换而受到影响。即:0xFC 字节显示为0x3F(“?”)。我的猜测是 ASCII 范围之外的任何值也会丢失。

我尝试使用 Read(byte[] buffer,int offset,int count) 方法使用 SerialPort.ReadBufferSize 来查看我应该读取多少字节,但它总是返回几乎 5000 ,即使我试图从 UART 仅读取 8 个字节.我必须创建一个函数来将此数组修剪为更小的数组并使用它。即使效率不高,我也可以使用此方法,但有时使用它会导致数组越界执行错误。调试后我发现当我读取一个完整的零数组时会发生这种情况。

我最后一次尝试是使用此代码:

private void DataRec(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    byte[] myarray = new byte[200];
    int pos = 0;
    bool eol = false;
    while (!eol)
    {
        myarray[pos++] = (byte) sp.ReadByte();
        if (myarray[pos] == 0x7E) eol = true;
    }

    byte[] newarray = Recorta(myarray);
    this.Dispatcher.Invoke(new AtualizaCallBack(this.atualiza), new object[] { newarray });
    sp.DataReceived -= DataRec;
}

调试时,我从来没有到达byte[] newarray = Recorta(myarray); 断点,但没有错误。奇怪的是,每当事件再次触发(我告诉 UART 向我发送一个数据包)时,pos 变量不会以零开头。

对可能发生的事情有什么想法吗?

有一点值得一提:

  • 0x7E "~" 是我的行尾字符
  • 200 是我一次接收的最大字节数
  • UART 代码一次发送一个字节的数据,但只有在收到正确的请求后才能发送数据

【问题讨论】:

  • FC is 超出 ASCII 范围...可能这只是编码抖动?但是是的,使用基于byte 的API 应该更可靠。您是否在检查 ReadByte() 是否返回负数? (表示 EOF)
  • 马克,感谢您的意见。这也是我的怀疑......至于EOF,正如我所说,它是0x7E“〜”。

标签: c# serial-port


【解决方案1】:

您只是使用了错误的 SerialPort 类成员。 ReadLine() 和 ReadExisting() 返回字符串,但您的数据不能存储在字符串中。 0xFC 没有 ASCII 字符代码,因此它只是放弃并产生“无法转换该字节”值。这是0x3F,一个问号。

同样,ReadBufferSize 是一个固定数字,除非您重新分配该值。它设置了串行端口驱动程序在程序读取之前用来存储接收到的字节的缓冲区的大小。充其量你会对 BytesToRead 属性感兴趣。这会告诉您该缓冲区中有多少字节可供读取。

只需使用 SerialPort.Read() 方法。一定要注意它的返回值,它告诉你读取了多少字节。这几乎总是一个小数字,通常是一两个字节。串行端口很慢。您需要继续阅读,直到您得到设备的完整响应。在你得到那个 0x7E 的情况下。

【讨论】:

  • 只是想强调 OP(而不是 Hans) - BytesToRead 永远不应该用于检查完整的消息 - 它应该用于确定是否有更多数据同步可用(与messages基本无关)——例如,决定同步读取还是异步读取。大多数时候我看到人们使用 BytesToRead / DataAvailable / 等等 - 它被不当使用了。
  • 谢谢汉斯,我现在尝试使用BytesToRead 看看会发生什么...而且我的设备不是真正的串行设备。我正在使用USB端口,所以我认为速度不会成为问题。也许在这种情况下BytesToRead 会救我。
  • 不要使用BytesToRead,因为它是一个不断变化的值,很容易给你带来麻烦。请改用 Read() 的返回值。
  • 但是我怎么能事先知道数组的正确大小呢?另一方面,使用 BytesToRead 有点工作。我不再被困在处理程序中了。第一次读取效果很好,但在那之后我得到了错误的数据(要么错过了第一个字节,要么得到了最后一次读取的一部分)。
  • 您应该知道响应的最大大小。只需使您的阵列足够大以存储它。如果您不这样做,请改用List<Byte>。遇到这种“错过第一个字节”问题正是为什么你不应该使用 BytesToRead。用了两次就出问题了,第二次可能会变大。
【解决方案2】:

试试这个。我认为主要是你没有正确实现它。

    private byte[] ReadLine(SerialPort serialPort)
    {
        byte[] buffer = new byte[4096];
        int count = 0;

        for (; count < buffer.Length; count++)
        {
            buffer[count] = (byte)serialPort.ReadByte();
            if (buffer[count] == 0x7E) break;
        }

        return buffer.Take(count);
    }

【讨论】:

  • 没有像我预期的那样工作。使用汉斯方法。但是感谢您记得我关于Take。虽然你最后错过了.ToArray()。否则会出现编译错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-24
  • 2011-08-27
  • 1970-01-01
  • 2018-06-14
相关资源
最近更新 更多