简体   繁体   English

使用c#从串口端口接收消息

[英]Receiving messages part by part from serial port using c#

I am using the below code to receive the messages from serial port using c# 我使用以下代码使用c#从串口接收消息

    void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        if (comPort.IsOpen == true)
        {
            string msg = comPort.ReadExisting();
            MessageBox.Show(msg.Trim());
        }
    }

The problem is, i am getting the messages part by part. 问题是,我逐个收到消息。 Like, if u send "Hello, How are you" I am receiving it word by word. 就像,如果你发送“你好,你好吗”,我会逐字接收。 I want that in a single stretch. 我希望在一个方面。 How can i do ?? 我能怎么做 ??

Also, is it possible to retrieve the port name from which the application is sending and receiving messages ? 此外,是否可以检索应用程序发送和接收消息的端口名称?

By far the easiest way to transmit a fixed amount of data over a serial port in one shot is to prepend the data with a length header. 到目前为止,一次性通过串行端口传输固定数据量的最简单方法是使用长度标头预先添加数据。 Use a fixed number of bytes for the length (2-4 should suffice) and then read length bytes of data synchronously using the Read method. 对于长度使用固定数量的字节(2-4应该足够),然后使用Read方法同步读取length字节数据。 You can do this asynchronously too, of course, you just need to save the length in a member field somewhere and perform your post-processing as soon as the length is hit. 您也可以异步执行此操作,当然,您只需将长度保存在某个成员字段中,并在命中长度后立即执行后处理。

The next-best way is to append a stop character or word. 下一个最好的方法是附加一个停止字符或单词。 If it happens to be a newline, then you can use the synchronous SerialPort.ReadLine method. 如果它恰好是换行符,那么您可以使用同步SerialPort.ReadLine方法。 Otherwise, collect the received data in a StringBuilder , keep appending to the StringBuilder until you hit the stop character, then return the contents of that StringBuilder up to (but excluding) the stop character. 否则,在StringBuilder收集接收到的数据,继续追加到StringBuilder直到你点击停止字符,然后将该StringBuilder的内容返回到(但不包括)停止字符。

If you do not have control over the source data, need to read a fixed amount of data, and don't know what that size is in advance, then your job is going to be considerably more difficult. 如果您无法控制源数据,需要读取固定数量的数据, 并且事先不知道该大小是多少,那么您的工作将变得更加困难。 I think the only way of really dealing with this situation is to wait for a predetermined timeout, at which point you assume that the transmission is over if you haven't received any new data. 我认为真正处理这种情况的唯一方法是等待预定的超时,此时如果您没有收到任何新数据,则假设传输结束。 It's not particularly reliable, which is why most communication protocols use one of the aforementioned designs. 它不是特别可靠,这就是大多数通信协议使用上述设计之一的原因。

If you think about the way a serial port (or any port) works, by simply pushing bits over a wire, then it should be clear that there's no way to know whether or not a transmission has completed without being able to predict the future. 如果您考虑串口(或任何端口)的工作方式,只需通过线路推送位,那么应该清楚的是,无法知道传输是否已完成而无法预测未来。 If you're connected to a remote host, ie over a modem, and that host disconnects you when the transmission is finished, then you might be able to use the Carrier Detect, but that doesn't sound like the case here. 如果您连接到远程主机,即通过调制解调器,并且该主机在传输完成后断开连接,那么您可以使用载波检测,但这听起来不像这里的情况。

Hopefully this is not the scenario you're currently in, and either you have some ability to control the source data or the device you're connecting to already uses a length header and/or stop pattern. 希望这不是您目前所处的场景,并且您有能力控制源数据或您正在连接的设备已使用长度标题和/或停止模式。 If it does, definitely use that. 如果确实如此,一定要使用它。 Otherwise, you'll probably be stuck using timeouts. 否则,您可能会遇到使用超时的问题。

   private void MonitorSP_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                System.IO.Ports.SerialPort SP = (System.IO.Ports.SerialPort)sender;

                //Get the ports available in system
                string[] theSerialPortNames = System.IO.Ports.SerialPort.GetPortNames();
                string strAvlPortNames = "";
                foreach (string s in theSerialPortNames)
                {
                    strAvlPortNames += s.ToString() + ", ";
                }

                //Read an contruct the message
                Thread.Sleep(1000);
                string msg = SP.ReadExisting();
                string ConstructedMsg = "Port's Found : " + strAvlPortNames + "\n" + "Port Used : " + SP.PortName + "\n" + "Message Received : " + msg;

                if (InvokeRequired)
                {
                    richTextBox1.Invoke(new MethodInvoker(delegate { richTextBox1.Text = ConstructedMsg; }));
                    //Send acknowlegement to sender port
                    SP.Write(SP.PortName);
                    return;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.StackTrace.ToString());
            }
        }  

尝试阅读直到你达到CRLF

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM