Wait for response from the Serial Port and then send next data

后端 未结 2 982
暗喜
暗喜 2020-11-30 14:54

I am reading data in bytes from .bin file and split the whole byte data into 16-16 bytes frames, so I want to 16 bytes frame one by one and wait un

2条回答
  •  [愿得一人]
    2020-11-30 15:35

    What you need is a way to block the execution of some code, until something else has happened, or - how to get things running on two threads synchronously. .NET has quite a few classes in the System.Threading namespace for synchronization. We'll use AutoResetEvent here.

    Think of AutoResetEvent as a turnstile.

    You can't move forward if the the person on the other side stops. When you move forward, you call Wait - and it blocks you from moving, until someone calls Set on it.

    Now if we apply that to our problem: We need to stop sending data until we get an acceptable response. So call Wait when sending data, and let the response handling code call Set to let it move forward.

    Here's an example which simulates a modem. You send some AT commands, it responds, but the responses always end with \r\n.

    var port = new SerialPort("COM2");
    port.Open();
    
    var mre = new AutoResetEvent(false);
    var buffer = new StringBuilder();
    
    port.DataReceived += (s, e) =>
    {
        buffer.Append(port.ReadExisting());
        if (buffer.ToString().IndexOf("\r\n") >= 0)
        {
            Console.WriteLine("Got response: {0}", buffer);
    
            mre.Set(); //allow loop to continue
            buffer.Clear();
        }
    };
    
    
    var commandsToSend = new string[] { "AT", "AT", "AT+CSQ" };
    var responseTimeout = TimeSpan.FromSeconds(10);
    
    foreach (var command in commandsToSend)
    {
        try
        {
            Console.WriteLine("Write '{0}' to {1}", command, port.PortName);
            port.WriteLine(command);
    
            Console.WriteLine("Waiting for response...");
    
            //this is where we block
            if (!mre.WaitOne(responseTimeout))
            {
                Console.WriteLine("Did not receive response");
                //do something
            }
        }
        catch (TimeoutException)
        {
            Console.WriteLine("Write took longer than expected");
        }
        catch
        {
            Console.WriteLine("Failed to write to port");
        }
    }
    
    Console.ReadLine();
    

    Sample output when tested through virtual serial port: (I just reply with OK)

    Write 'AT' to COM2
    Waiting for response...
    Got response: OK
    
    Write 'AT' to COM2
    Waiting for response...
    Got response: OK
    
    Write 'AT+CSQ' to COM2
    Waiting for response...
    Did not receive response
    

提交回复
热议问题