【问题标题】:Why SerialDataReceivedEventArgs receive incomplete data?为什么 SerialDataReceivedEventArgs 收到不完整的数据?
【发布时间】:2019-12-07 03:20:05
【问题描述】:

我目前正在研究 IO 板。串行对象已初始化并侦听传入数据。我正在使用 SerialPort1.ReadExisting(); 读取传入的数据,因为传入的字符串预计在每次读取时都会以 {X000000}5E + \r\n 的形式到达。

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    try
    {
        TextBox2.Invoke(new EventHandler(delegate
        {
            TextBox2.AppendText(SerialPort1.ReadExisting());
        }));
    }
    catch
    {
        MessageBox.Show("Couldn't open Port", "Error");
    }
}

当像这样使用 ReadExisting() 时,我得到了我想要的结果,我会得到 "{X" 和 "}" 之间的值,但是当我做一个拆分字符时,我总是得到关于索引的错误越界。我通过在读取时添加Environment.NewLine来更改读取方式以获取数据是否完整接收。结果将如下图所示。

我也尝试根据 SO 回答如下,但传入的字符串数据将与上图相同:-

var end = '\r';
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);

string RxString = System.Text.Encoding.ASCII.GetString(data);
LogEvents($"Serial port data: {RxString}");

这就像 {X000000}5E 的全套将分到 SerialDataReceivedEventArgs 1-3 次。

我读错了吗?我还将波特率从 9600 增加到 19200,但传入的数据仍然与提供的图像相同。和IO板程序有关系吗?我不太确定。

【问题讨论】:

  • “但是当我做一个拆分字符时,我总是收到关于索引超出范围的错误”......在帖子的代码示例中没有任何类似的东西......请查看@987654322 @关于发布代码的指导。
  • @AlexeiLevenkov,声明是因为我有 6 组按钮附加到 IO 板上。每个按钮代表 000000 的索引。如果按下按钮 #2,结果将是 {X010000}5E。我必须对数据进行子串化并从索引 2、长度 6 中获取记录到 ToCharArray() 并找到索引 int i = Array.IndexOf(charData, '1'); 当我在当前代码和子字符串中读取时,如果传入的数据不完整,则会出错 { X######}5E.
  • 串口不保证在一个块中接收到所有发送数据。 Windows 使用计时器在应用程序和硬件接口之间转发串行端口数据。波特率只是传输速率而不是实际发送速率。如果设备每秒只发送 1 个字符,则传输速率仍然可以是 9600。例如,假设应用程序每分钟发送一次时间,并且时间消息包含 10 个字符。以 9600 的传输速率,您将每分钟获得 10 个字符。
  • @jdweng,所以它取决于设备?因为 io 板的程序员将在 2-3 天内到我这里。我只是知道收到的数据取决于您的详细信息的设备容量。
  • 您可能会传输以回车符结尾的 ASCII 数据。多年来完成了一个与程序员交互的软件。

标签: c# serial-port


【解决方案1】:

正如@jdweng 所指出的,串行端口DataReceived 事件有些随机触发。它可以触发中间字符串,您只能收到一半的消息。你必须建立自己的字符串。大多数串行到串行通信使用回车符 (\r) 或换行符 (\n) 来确定消息已完成。根据您告诉我们的内容,您似乎在末尾添加了 <CR><LF>,因此我们可以查找 LF 以知道我们得到了整个字符串。

char LF = (char)10;
StringBuilder sb = new StringBuilder();
string currentLine = string.Empty;

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    string Data = serialPort1.ReadExisting();

    foreach (char c in Data)
    {
        if (c == LF)
        {
            sb.Append(c);

            CurrentLine = sb.ToString();
            sb.Clear();

            //parse CurrentLine here or print it to textbox
        }
        else
        {
            sb.Append(c);
        }
    }
}

所以在上面的例子中,我正在寻找一个换行符来知道我得到了整个消息。 (LF 或\n)。

【讨论】:

    猜你喜欢
    • 2021-10-01
    • 2012-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多