C#等待串行端口上的回声,检查,并且对等待timout [英] c# wait for an echo on serial port, check it, and have a timout on the wait

查看:143
本文介绍了C#等待串行端口上的回声,检查,并且对等待timout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,感谢您考虑这个查询:
我从一台PC通过虚拟串口发送命令到它回显在嵌入式系统已完成命令的命令嵌入式系统

Hello and thanks for considering this query: I am sending a command from a PC over a virtual serial port to an embedded system which echos back the command when the embedded system has completed the command.

我可以发送命令精细,看到了回声,当命令被嵌入系统正完成,但我无法找到一个合适的方式来等待或拖延程序,直到呼应命令收到,这样我可以继续发送下一个命令。我想它的一个类型,我试图实施高层次的流量控制。
的代码是用C#。
我想等待来回回波并有一个超时以及万一通信PC和嵌入式系统之间的丢失,所以该方案不冻结。
任何威兹的孩子在那里,可以提出一个整洁的方式做到这一点?
我不是一个伟大的C#程序员,刚学

I can send the command fine and see the echo, when the command is completed by the embedded sytem, but I am having trouble finding a suitable way to wait or delay the program until the echoed command is received, so that I may proceed and send the next command. I suppose its a type of "high level" flow control that I'm trying to implement. The code is in C#. I'd like to wait fro the echo and have a timeout as well in case communication is lost between the PC and embedded system, so that the program does not freeze. Any wizz kids out there that can suggest a neat way to do this? I am not a great c# programmer, just learning.

这是接收功能,我有:

    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        // If the com port has been closed, do nothing
        if (!comport.IsOpen) return;

        // This method will be called when there is data waiting in the port's buffer

        // Determain which mode (string or binary) the user is in
        if (CurrentDataMode == DataMode.Text)
        {
            // Read all the data waiting in the buffer
            string data = comport.ReadExisting();

            // Display the text to the user in the terminal
            Log(LogMsgType.Incoming, data);
        }
        else
        {
            // Obtain the number of bytes waiting in the port's buffer
            int bytes = comport.BytesToRead;

            // Create a byte array buffer to hold the incoming data
            byte[] buffer = new byte[bytes];

            // Read the data from the port and store it in our buffer
            comport.Read(buffer, 0, bytes);

            // Show the user the incoming data in hex format
            Log(LogMsgType.Incoming, ByteArrayToHexString(buffer));
            }
    }

这是一个电话要传输的一个命令的例子

This is an example of a call to Transmitt a command:

     text = "AR" + 50 + "\r";            //transmit a command to move
     this.comport.Write(text);

目前我使用的时间延迟了Thread.Sleep(TIMEGAP),并假设该消息被执行,使回波从嵌入式系统恢复是不错,但我不检查,还将等待很长的时间,以确保它完成:

Currently I'm using a time Delay [Thread.Sleep(TIMEGAP)] and assuming that the message is executed and that the echo back from the embedded system is fine BUT I do not check it and also wait a very long time to ensure that it is completed:

     text = "AR" + 50 + "\r";            //transmit a command to move
     this.comport.Write(text);
     Thread.Sleep(TIMEGAP);              //Timegap = 10000ms



我真的想更换的时间延迟调用[Thread.sleep代码(TIMEGAP )〕与功能/方法,它监视串行端口的响应,检查看,这是相同的一个上发送,然后允许该程序代码,以进行到下一个命令,并且如果正确的回波[AR50\在上面的例子中R]是不是在说收到例如5秒钟,然后程序会报告错误。

I really would like to replace the time delay call [Thread.Sleep(TIMEGAP)] with a function/method that monitors the response on the serial port, checks to see that it is the same as the one sent and then allows the program code to proceed to the next command, AND if the correct echo [AR50\r in the above example] is not received in say for example 5 seconds, then the program reports an error.

有什么建议?

感谢您!

推荐答案

最简单的方法是不使用 DataReceived 事件,而是通过设置的 ReadTimeout 并使用方法。

The easiest way is not to use the DataReceived event, but by setting a ReadTimeout and using the Read method.

既然你正在处理的ASCII,你应该检查出的 的ReadLine 方法。

And since you're dealing with ASCII, you should check out the ReadLine method.

双方将抛出的 TimeoutException异常 如果 ReadTimeout 已过去没有进入的数据。

Both will throw a TimeoutException if ReadTimeout has elapsed without incoming data.

如果,但是,嵌入式系统可以发送未经请求的消息时,你需要一个另一种方法。然后,你可以把你在一个全局字符串变量期待回声,并有接收事件设置的 的ManualResetEvent 时,已收到回音。然后你就可以等待的ManualResetEvent 一个超时。这也将使用 <$ C 。$ C>锁定 声明

If, however, the embedded system can send unsolicited messages, the you'll need an other approach. Then you could put the echo you're expecting in a global string variable, and have the receive event set a ManualResetEvent when the echo has been received. Then you can wait for the ManualResetEvent with a timeout. This will also involve thread synchronization using the lock statement.

如果GC是不是一个问题,我可能会像这样开始:

If GC is not an issue, I would probably start with something like this:

using System.Text;
using System.IO.Ports;
using System.Threading;

namespace ConsoleApplication2
{
    class Program
    {
        static string serialBuffer = "";
        static string expectedEcho = null;
        static object expectedEchoLock = new object();
        static ManualResetEvent expectedEchoReceived = new ManualResetEvent(false);
        static SerialPort port = new SerialPort("COM1", 19200, Parity.None, 8, StopBits.One);

        static void Main(string[] args)
        {
            port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
        }

        static void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            while (port.BytesToRead > 0)
            {
                byte[] buffer = new byte[port.BytesToRead];
                int bytesRead = port.Read(buffer, 0, buffer.Length);
                if (bytesRead <= 0) return;
                serialBuffer += Encoding.UTF8.GetString(buffer, 0, bytesRead);
                string[] lines = serialBuffer.Split('\r', '\n');
                // Don't process the last part, because it's not terminated yet
                for (int i = 0; i < (lines.Length - 1); i++)
                {
                    if (lines[i].Length > 0)
                        ProcessLine(lines[i]);
                }
                serialBuffer = lines[lines.Length - 1]; // keep last part
            }
        }

        static void ProcessLine(string line)
        {
            bool unsolicitedMessageReceived = false;
            lock (expectedEchoLock)
            {
                if (line == expectedEcho)
                {
                    expectedEchoReceived.Set();
                }
                else
                {
                    unsolicitedMessageReceived = true;
                }
            }
            if (unsolicitedMessageReceived)
            {
               // Process unsolicited/unexpected messages
            }
        }

        /// <summary>
        /// Send a command and wait for echo
        /// </summary>
        /// <param name="command">The command to send</param>
        /// <returns>True when echo has been received, false on timeout.</returns>
        static bool SendCommand(string command)
        {
            lock (expectedEchoLock)
            {
                expectedEchoReceived.Reset();
                expectedEcho = command;
            }
            port.Write(command);
            return expectedEchoReceived.WaitOne(5000); // timeout after 5 seconds
        }
    }
}

这篇关于C#等待串行端口上的回声,检查,并且对等待timout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆