C#SerialPort侦听端口

时间:2017-03-23 12:45:10

标签: c# serial-port serial-communication

我正在尝试在微处理器和c#表单应用程序之间进行串行通信。

问题是,来自微处理器的数据可以在2秒或5秒或10秒内完成。我的意思是没有特定的时间,我想听端口并获取数据,如果它是2秒,如果不是,等待数据,直到它来。

我尝试使用serialport.readline();但是当readline阻塞时,表单会挂起,所以当我这样做时,我试图与backgroundworkers一起工作,当backgroundworker忙时,我无法关闭表单,因为readline命令会阻止整个程序。

我所说的是,请告诉我一些关于收听端口的线索,而未来的数据时间并不具体。

感谢您的时间(抱歉英语不太好)

2 个答案:

答案 0 :(得分:1)

您可以使用SerialPort.DataReceived Event获取数据异步。在创建SerialPort类的实例后,您可以向SerialPort添加事件处理程序。如果收到数据,则调用事件处理程序。

mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

在处理程序内部,您可以从输入缓冲区中读取数据并使用它执行任何操作。

private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    string indata = sp.ReadExisting();
    //Do what ever you want with the data
}

这是一种非常常见的解决方案,可以在不正常的时间步骤中获取数据,从而在不阻止应用程序的情况下运行应用程序。

答案 1 :(得分:1)

您可以使用DataReceived事件。每当新数据到达您的端口时,它都会被触发。你需要像这样注册:

SerialPort port = new SerialPort(/*your specification*/);
port.DataReceived += Port_DataReceived;

在事件处理程序中,您将读出传入的数据

private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort port = sender as SerialPort;

    if (port != null)
    {
        var incoming_message = port.ReadExisting();
    }
}

现在您只需打开端口即可自动收听。注意!传入的数据将到达与主线程不同的线程。因此,如果您想使用表单的控件进行显示,则需要使用BeginInvoke

如果您的数据标记在最后\n,则可以尝试使用ReadLine方法:

var incoming_message = port.ReadLine();

或者您可以尝试ReadTo

var incoming_message = port.ReadTo("\n");

修改

如果这么长时间,你应该分批阅读。您也可以尝试在while循环中处理它。

private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort port = sender as SerialPort;

    string message = "";
    if (port != null)
    {

        while(port.BytesToRead > 0)
        {
            message += port.ReadExisting();
            System.Threading.Thread.Sleep(500); // give the device time to send data
        }
    }
}

编辑2:

如果要存储数据,请在事件处理程序之外声明List<string>,并在完全读取时添加字符串。

List<string> dataStorage = new List<string>();


private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort port = sender as SerialPort;

    string message = "";
    if (port != null)
    {

        while(port.BytesToRead > 0)
        {
            message += port.ReadExisting();
            System.Threading.Thread.Sleep(500); // give the device time to send data
        }
        // add now the entire read string to the list
        dataStorage(message);
    }
}

由于事件处理程序不知道您是否已发送AB,只需在一个列表中收集整个收到的消息。您知道发送命令的顺序,因此稍后您可以取出相应的消息并使用Split获取数组中的400个条目:

string [] A_array_data = dataStorage[0].Split(" ");