同步串口读/写

时间:2011-05-10 16:31:52

标签: c# synchronization serial-port

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

}

3 个答案:

答案 0 :(得分:0)

我会在类中使用一个bool变量和一个计时器。当计时器滴答时,你检查bool并在允许的情况下发送数据。

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

答案 1 :(得分:0)

我过去也有同样的问题,我这样解决了:

我添加了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!!!
            }
        }

答案 2 :(得分:0)

如果要检查是否有发送到设备的字节(写缓冲区中的字节),那么您可以读取BytesToWrite属性。

SerialPort.BytesToWrite Property