【问题标题】:C# SerialPort Listening PortC# SerialPort 监听端口
【发布时间】:2017-03-23 12:45:09
【问题描述】:

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

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

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

我的意思是,请给我一些关于在即将到来的数据时间不具体时监听端口的线索。

感谢您的宝贵时间(抱歉英文不好)

【问题讨论】:

  • 你有任何代码示例可以给我们看吗?
  • 尝试向 stackoverflow 添加新的
  • 在您的表单关闭事件中,也许您也可以尝试在串口上调用Close()。如果您使用的是BackgroundWorker,那应该会取消阻止读取调用,不是吗?

标签: c# serial-port serial-communication


【解决方案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
}

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

【讨论】:

  • 但我只得到一个数据,例如,当我将 A 写入串行端口时,我得到 400 个数据,数据之间有一个空格,数据以“!”开头并以“\n”结尾,所以我使用数组,如果我像你说的那样写数组是不可靠的。
  • 你能举个例子吗?
  • @oakar 用空格分割字符串,得到一个包含 400 个元素的字符串 []
  • 我试图发帖,但网站说添加到我不知道该怎么做的问题是不合适的
  • 是的,我使用了拆分,但读取现有()对我不利,因为当 400 到来时,它并没有等待整个数据
【解决方案2】:

您可以使用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(" ");

【讨论】:

  • 我使用了这个,但 Read.existing() 不等待整个数据,例如当我将 A 写入串行端口时,我得到 400 个数据,数据之间有空格,数据以“!”开头并以“\n”结尾,所以我使用数组,如果我像你说的那样写数组是不可靠的(我使用拆分)
  • @oakar 设备传输 400 个字节需要多长时间?是字节吗?还是 400 个字符?
  • 这是一个电子板,它有继电器。当我对端口说 A 时,它读取端口并触发继电器,然后它测量电压并写入端口,我以 c# 形式显示它需要 3 秒我必须在继电器执行此操作时监听
  • 我试过它会阻止整个程序,这就是我使用后台工作程序的原因,然后我无法关闭 readline 阻止程序@Mong Zhu
  • @oakar 在您使用 readexisting 读取第一批之后,其余输入会发生什么?事件会再次触发吗?
猜你喜欢
  • 2012-05-17
  • 2016-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-20
相关资源
最近更新 更多