【问题标题】:Serial port data is coming duplicated or resent (some chars)串行端口数据重复或重新发送(一些字符)
【发布时间】:2013-02-05 12:51:44
【问题描述】:

让我解释一下场景:给我带来数据(字符串)的串口,如下例:

02051014 0009 M 0 741 30041105 2632 0 30041105

我尝试过各种读取(读取、读取字节、读取字符、读取行、读取现有)。我试图更改new line,但数据一直重复。看看上面的例子,现在看看数据是怎么来的:

0220510114 00009 M 0 741 300441105 2632 0 300411055

有人知道我该如何解决这个问题吗?

代码:

[...]
try
{
    this.serialPort = new SerialPort("COM1", 2400, Parity.None, 7, StopBits.One);
    this.serialPort.DataReceived += new SerialDataReceivedEventHandler(portaSerial_DataReceived);
    this.serialPort.Handshake = Handshake.XOnXOff;
    this.serialPort.Encoding = Encoding.ASCII;
    this.serialPort.Open();
}
[...]
private void portaSerial_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    try
    {
        var invalidValuesToBreakLine = new int[] { 13, 10, 0 };
        int data;

        while (this.serialPort.BytesToRead > 0)
        {
            data = this.serialPort.ReadChar();

            if (invalidValuesToBreakLine.Contains(data))
            {
                if (!this.breakLineWasPerformed)
                {
                    this.breakLineWasPerformed = true;

                    this.dataList.Add(this.temporaryString);

                    this.temporaryString = string.Empty;
                }
            }
            else
            {
                if (this.breakLineWasPerformed)
                {
                    this.breakLineWasPerformed = false;
                }

                this.temporaryString += (char)data;
            }
        }
[...]

【问题讨论】:

  • 您是否正确设置了波特率、奇偶校验等?可能是连接有问题并尝试重新发送?
  • 我没有看到重复的数据。您确实了解串行数据的传输方式吗? 发布您的代码。
  • @Ramhound:请进一步解释一下为什么字符串末尾的双倍 2 和双倍 5 是正常的?
  • @ThorstenDittmar - 显然作者得到的值是错误的,它不正常,但它不是重复的数据。出于某种原因,正在重新发送一个字节。我怀疑处理字节读取方式的代码。 由于我高度怀疑您知道答案,所以我会让您回答您自己的问题。我厌倦了在我对自己的投反对票提供反馈后,人们在这个社区中投反对票。
  • @Ramhound:我明白了,我虽然你没有在消息中看到额外的 2 和 5:-D

标签: c# .net serial-port


【解决方案1】:

我会尝试的第一件事是在每次调用 ReadChar() 方法后将 data 重置为空字符串,或者刷新输入缓冲区。

我怀疑对 BytesToRead() 的调用返回大于零,但 ReadChar() 调用返回串行端口缓冲区上的原始字符。这是由于串行端口的内部时序,以及您的代码对于硬件设备而言可能“运行得太快”这一事实。

我可能会重新考虑方法中的整个 while 循环。您可能可以简化很多,只需尝试以下(使用您的自定义代码)

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    string indata = sp.ReadExisting();
    Console.WriteLine("Data Received:");
    Console.Write(indata);
}

要更改您的换行符,只需检查 indata 字符串并在您的字符上换行,将结果存储在全局变量中,然后重用剩余的数据。

【讨论】:

  • 再次...重复字符。
  • 是否可以清除我从缓冲区获取的最后一个字符?
【解决方案2】:

经过挖掘,我发现了这个StackOverflow question / answer,这表明DataReceived 事件可能会在意想不到的时间触发。所以,如果可能的话,你应该设置一个NewLine 并触发它。

作为对这个想法的测试,您可以尝试添加一个按钮并等待,直到您知道您有一些数据,然后单击它以向您显示流。如果没有重复,则表明 DataReceived 事件过于急切且触发不正确。然后您可能需要检查您的NewLineDtrEnableDsrHolding 等。

private void TestButton_Click(object sender, EventArgs e)
{
    string indata = this.serialPort.ReadExisting();
    MessageBox.Show(indata);
}

【讨论】:

  • 是的。 "我试过各种读法(读、读字节、读字符、读行、读现有)"
  • @ViniciusOttoni - 好的,我已经改变了我的答案以尝试另一个想法,并且不再使用可靠的 DataReceived 事件!
  • 无法知道数据何时可用。 =/所以,我放了一个线程来做这件事,一直在请求是否有可用的数据,同样的事情,重复的字符。 =(
  • 当然,这从来都不是解决方案,只是想看看它是否能解决您的问题!你说线程,它是不是和我在这里做的一样,所以只是抓取数据而不会太聪明?
  • 我需要一直放一个线程来获取可用数据,因为我要更新数据,它是一个在线系统。
猜你喜欢
  • 2012-12-19
  • 2012-01-29
  • 1970-01-01
  • 2013-11-07
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多