代码之家  ›  专栏  ›  技术社区  ›  GONeale

需要.NET串行端口帮助,主要是在多个“数据包”中接收数据

  •  2
  • GONeale  · 技术社区  · 16 年前

    我对通过.NET通过串行端口发送数据非常陌生,我注意到在实现了一个与TCP对应的协议之后,使用串行端口就不那么容易了!

    因此,从最高层开始,我的串行双向通信实现就快实现了,我只需要做一些事情:

    1. 我的读操作被拆分为多条消息,或者在COM端口上以碎片响应的形式接收,我不知道可能需要什么设置,也不知道应该如何以不同的方式编写代码来解决这个问题。什么会导致这种情况?我正在上的断点处检查消息 SerialPort_DataReceived.

    基本上,数据应发送为:

    01: LS|DA090521|TI111043|q
    02: PS|RN102|PTC|TA1040000|P#0|DA090521|TI111429|j
    

    但它正在被拆分(在每个请求读取的随机位置)

    01: LS|DA090521|TI111
    02: 043|q
    03: PS|RN102|PTC|TA1
    04: 0000|P#0|DA090521|TI111429|j
    

    -问题1已经回答,谢谢Chris W.和其他人!现在我有了一条消息,我希望它是从片段逐步构建的(寻找stx,msg body,etx),然后在消息完全构建后执行一个操作,并使它与线程安全队列一起运行,非常高兴。

    . 2。我几乎每一个周期都会收到一个“”符号,这是因为我设置错误的命令、串行通信的伪影还是设备发送给我的东西?(不过,我不这么认为,因为超级终端连接显示这个字符没有被连续发送。)

    . 三。你能确认我在各自的方法中正确地读写数据吗?

    谢谢大家也看了我的另外两个问题。

    相关规范如下:

    ...
        //                          COM3,    9600,     None,   8,        One
        SerialPort = new SerialPort(comPort, baudRate, parity, dataBits, stopBits);
        if (SerialPort.IsOpen) SerialPort.Close();
        // SerialPort.RtsEnable = true; // Request-to-send
        // SerialPort.DtrEnable = true; // Data-terminal-ready
        SerialPort.ReadTimeout = 150; // tried this, but didn't help
        SerialPort.WriteTimeout = 150; // tried this, but didn't help
        SerialPort.Open();
    
        SerialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);
    }
    
    void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        // Process received data
        SerialPort sp = (SerialPort)sender;
        byte[] buffer = new byte[sp.BytesToRead];
        int bytesRead = sp.Read(buffer, 0, buffer.Length);
    
        // message has successfully been received
        message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
    }
    
    public bool SendMessage(string text)
    {
        // Only send message if a client is connected
        if (SerialPort != null && SerialPort.IsOpen)
        {
            byte[] buffer = Encoding.ASCII.GetBytes(text);
            SerialPort.Write(buffer, 0, buffer.Length);
        }
    }
    
    3 回复  |  直到 16 年前
        1
  •  4
  •   ChrisW    16 年前

    我的阅读被分成多条信息

    这是正常的、预期的、不可避免的行为。在TCP上的数据也可能发生这种情况。对于串行接口来说,这只是一个无休止的字节流。应用程序负责将这些字节重新打包成数据包。

    如果数据包边界的位置很重要,并且您无法通过查看接收到的数据来判断数据包边界的位置,那么您可能需要重新考虑数据的格式,以便 可以 告诉包边界在哪里。

    我几乎每一个周期都会收到一个“”符号。

    那个字符的十六进制值是多少?查看是否设置 Handshake 属性到 XOnXOff RequestToSendXOnXOff 改善情况。

        2
  •  3
  •   mtrw    16 年前

    在较低的级别,串行端口可以决定何时触发数据接收事件。它可能会在“满”包到达之前决定这样做。但是,看起来您的预期数据集中有一个终止符字符。如果是这样,您可以执行以下操作(注意,我已经更改了您的serialport分配以避免语法混乱:

            p = new SerialPort(PortName, BaudRate, Prty, DataBits, SBits);
            p.NewLine = Terminator;
    

    其中,terminator是包含终止字符的字符串。然后可以使用serialport.readline()(如果适用,还可以使用serialport.writeline())。这至少对你的第一个问题有帮助。

        3
  •  3
  •   gonzobrains Etienne Lawlor    12 年前

    我已经做了很多win32串行端口编程,但是对.net只做了一点,所以请接受我的建议。

    我的读操作被拆分为多条消息,或者在COM端口上以碎片响应的形式接收,我不知道可能需要什么设置,也不知道应该如何以不同的方式编写代码来解决这个问题。

    正如其他人所说,这是完全正常的。根据DCE侧的设备类型,您可能需要自己重新包装。我不知道你连接了什么类型的设备,所以我不能说更多。

    如果要获取更多数据,可以尝试以下操作:

    • 调整System.Int32 ReceiveDBytesthreshold属性
    • 使用同步I/O并指定要读取的固定字节数,而不是基于事件的接收

    我几乎每一个周期都会收到一个“”符号。 这是因为我设置了一个命令 不知怎么的,一个系列的人工制品 通信,或者设备 是送我吗?(我不这么认为 但是,作为超级终端连接 显示这个角色不是 连续发送。)

    如果你对排队的事很好奇,那就去看看吧。 PortMon from SysInternals 这是一个免费的应用程序,可以在您通过线路传输数据时窥探您的COM端口。这似乎是技术性的,但实际上你只需要看看irp-mj-write和irp-mj-read命令,在这行中你可以看到字节长度和通过线路发送的数据。通过这个,您应该能够知道问题是.NET serialport对象,还是设备正在通过该行发送“”。

    你能确认我在读并且 在中正确写入数据 各自的方法。

    它看起来适合于基于事件的数据接收方法。

    推荐文章