同步串行端口读/写

本文关键字:串行端口 同步 | 更新日期: 2023-09-27 17:55:45

我正在尝试在Visual Studio 2010中编写一个通过串行连接与微控制器通信的c#程序。我可以很好地读取和写入端口,我只是不确定如何让 send 方法等到收到上一个发送命令中的所有数据后再执行。我已经实现了数据接收事件处理程序,以便它确定何时在串行端口上接收了请求的适当数量的数据。我只需要知道如何让它告诉发送方法端口是免费的。

我曾计划使用互斥锁,但我相信问题不是由于多线程造成的。同一线程在串行端口上一个接一个地发送字符串,并且响应第一个请求而接收的数据与第二个请求冲突。

此外,如果通信由一个线程完成,让该线程等待是否会导致接收的数据事件处理程序无法执行?

(两种方法在同一个类中)

我的发送数据方法:

//method for sending data
public void send(String s)
{
    sp.Write(s + "'r");
}

我的数据接收事件处理程序:

//data received event handler
private void dataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    string tmp;
    tmp = sp.ReadExisting();
    //put all received data into the read buffer
    readBuffer += tmp;
    //add various flag checks to determine end of transmission
    if (firmwareFlag)
    {
        if (readBuffer.EndsWith("'n"))
        {
            firmwareFlag = false;
            //trigger event to tell object owner data is ready
            dataReady(this, new CustomEventArgs(readBuffer, "firmware"));
            readBuffer = "";
        }
    }
    else if (parameterFlag)
    {
        if (System.Text.RegularExpressions.Regex.IsMatch(readBuffer, "K90", System.Text.RegularExpressions.RegexOptions.IgnoreCase))
        {
            parameterFlag = false;
            dataReady(this, new CustomEventArgs(readBuffer, "parameters"));
            readBuffer = "";
        }
    }
    else
    {
        dataReady(this, new CustomEventArgs(readBuffer, null));
        readBuffer = "";
    }
}

同步串行端口读/写

我会在类中只使用一个布尔变量和一个计时器。当计时器滴答作响时,您检查该布尔值并在允许的情况下发送数据。

boolean isAllowed;
DispatcherTimer tmr1;
//...etc

我过去有同样的问题,我用这种方式解决了:

我添加了 SendAndWaitResponse 方法,该方法接收端口要发送的缓冲区、响应的预期长度、以秒为单位的超时(以防万一)和回调,当收到预期的响应时:

//System.IO.Ports.SerialPort port; 
        //port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived);
        void SendAndWaitResponse(String buffer, int expectedLenght, int timeoutInSeconds, Action<String> callback)
        {
            TimeSpan _timeout = new TimeSpan(0, 0, 0, timeoutInSeconds);
            //may not be necesary
            if (!string.IsNullOrEmpty(buffer) && buffer != "" && port != null)
            {
                //Remove current dataReceived event handler, as we will manually manage it for now, will restore later!
                this.port.DataReceived -= port_DataReceived;
                if (!this.port.IsOpen) this.port.Open(); // open the port if it was closed
                this.send(buffer); // send buffer, changed port.write(buffer) so it now usses your own send
                DateTime startToWait = DateTime.Now; //start timeout
                bool isTimeout = false;
                int totalRead = 0;
                String read = "";
                while (!(isTimeout) && totalRead < expectedLenght)
                {
                    do
                    {
                        if (port.BytesToRead > 0)
                        {
                            read += (char)this.port.ReadByte();
                            totalRead++;
                            //you can add a System.Threading.Thread.Sleep(int); if all bytes come in parts
                        }
                    } while (port.BytesToRead > 0);
                    isTimeout = (DateTime.Now.Subtract(_timeout) >= startToWait);
                }
                this.port.DataReceived += port_DataReceived; // restore listener
                callback(read); //invoke callback!!!
            }
        }
如果要

检查是否有字节未发送到设备(写入缓冲区中的字节),则可以读取 BytesToWrite 属性。

SerialPort.BytesToWrite 属性