简体   繁体   English

C#SerialPort侦听端口

[英]C# SerialPort Listening Port

I am trying to do a serial communication between my micro processor and c# form application. 我正在尝试在我的微处理器和c#表单应用程序之间进行串行通信。

The problem is, data which comes from micro processor can come in 2 seconds or 5 seconds or 10 seconds. 问题是,来自微处理器的数据可能会在2秒或5秒或10秒后到达。 I mean there is no specific time and i would like to listen port and get data if it is come in 2 seconds if it is not, wait for the data until it comes. 我的意思是没有特定的时间,如果不是2秒钟,我想监听端口并获取数据,如果没有,请等待数据。

I tried to this with serialport.readline(); 我尝试使用serialport.readline(); but form hangs on while readline blocking, so i tried to do with backgroundworkers when i do this, i cant close form while backgroundworker is busy because readline command blocks the whole program. 但是在readline阻塞时窗体挂起,所以我尝试使用backgroundworkers这样做时,由于readline命令阻塞了整个程序,因此我无法在backgroundworker忙时关闭窗体。

All i am saying is, please give me some clue about listening the port while coming data time is not specific. 我只是说,请给我一些有关监听端口的线索,而即将到来的数据时间并不具体。

Thank you for your time (sorry for english it is not well) 谢谢您的时间(对不起,英语不好)

You can use the SerialPort.DataReceived Event to get the data async. 您可以使用SerialPort.DataReceived事件获取异步数据。 After you created an instance of the SerialPort class, you are able to add event handlers to the SerialPort . 创建SerialPort类的实例之后,可以将事件处理程序添加到SerialPort Thes event handlers are called if data was received. 如果接收到数据,则调用事件处理程序。

mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

Inside the handler you can read the data from the input buffer and do what ever you want with it. 在处理程序内部,您可以从输入缓冲区读取数据,然后执行所需的操作。

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

This is a very common solution to get data in unregular time steps which runs your application without blocking it. 这是一种非常常见的解决方案,可以以不规则的时间步获取数据,从而可以在不阻塞应用程序的情况下运行您的应用程序。

You can use the DataReceived event. 您可以使用DataReceived事件。 It will be fired everytime new data arrives at your port. 每当新数据到达您的端口时,它将被触发。 You need to register to it like this: 您需要这样注册:

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

In the event handler you would then read out the incoming data 然后在事件处理程序中读出传入的数据

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

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

Now you just need to open the port and it will listen automatically. 现在,您只需要打开端口,它将自动侦听。 NOTE! 注意! the incoming data will arrive on a different thread than the main thread. 传入的数据将到达与主线程不同的线程。 So if you want to use controls of your form for display you need to use BeginInvoke 因此,如果要使用表单的控件进行显示,则需要使用BeginInvoke

If your data is marked at the end with \\n you could try using the ReadLine method: 如果您的数据以\\n结尾,则可以尝试使用ReadLine方法:

var incoming_message = port.ReadLine();

Or you could try ReadTo 或者您可以尝试ReadTo

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

EDIT: 编辑:

If it is such a long time, than you should read it in batches. 如果时间太长,则应该分批阅读。 You could also try to handle it in a while loop. 您也可以尝试在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
        }
    }
}

EDIT 2: 编辑2:

If you want to store the data declare a List<string> outside of the event handler and add the string when it is entirely read. 如果要存储数据,请在事件处理程序之外声明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);
    }
}

Since the event handler does not know whether you have send A or B just collect the entire received messages in one list. 由于事件处理程序不知道您发送的是A还是B只需将整个接收到的消息收集在一个列表中即可。 You know the order in which you have send your commands, so later you can take out the corresponding message and use Split to get the 400 entries in an array: 您知道发送命令的顺序,因此以后您可以取出相应的消息并使用Split来获取数组中的400个条目:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM