3

我确实编写了一个小型 C# 应用程序,它从 COM 端口读取 Arduino 板发送的一系列数字。

问题:

如果 Arduino 每 500 毫秒发送一个值,但我的 C# 程序每 1 秒读取一个值,那么 C# 是否会落在 Arduino 后面?如果这是真的,从 Arduino 发送的数据是存储在缓冲区中还是被丢弃?

[编辑]

Bellow 是我用来从 COM 读取的代码


System.Windows.Forms.Timer tCOM;
...

tCOM.Interval = 1000;
tCOM.Tick += new System.EventHandler(this.timer1_Tick);
...

SerialPort port = new SerialPort();
port.PortName = defaultPortName;
port.BaudRate = 9600; 
port.Open();
.....

private void timer1_Tick(object sender, EventArgs e)
{
    log("Time to read from COM");

    //read a string from serial port
    string l;
    if ((l = port.ReadLine()) != null)
    {
    ......

    }

}
4

2 回答 2

4

串行端口通信通常需要流量控制。一种让发送器知道接收器已准备好接收数据的方法。这经常被忽视,尤其是在 Arduino 项目中。与最初开始使用串行端口的机器相比,串行端口非常慢,而现代机器速度非常快。

但很明显,在你的场景中,有些事情会爆炸!过了一会儿。当 PC 中的接收缓冲区已满时,您的 Arduino 将导致缓冲区溢出。这会导致无法挽回的数据丢失。侦听这种情况的通知是经常被跳过的其他事情,您必须为 SerialPort.ErrorReceived 事件注册一个事件处理程序。在这种情况下,您会收到 SerialError.Overrun 通知。没有干净的方法可以从这种情况中恢复,需要完整的协议重置。

有两种基本的方法可以在串口上实现流控来避免这个错误。最常见的一种是使用硬件握手,使用 RTS(请求发送)和 CTS(清除发送)信号。由 Handshake.RequestToSend 提供。当接收缓冲区太满时,PC 会自动关闭 RTS 信号。您的 Arduino 必须注意 CTS 信号,并且在关闭时不要发送任何内容。

第二种方式是软件握手,接收方发送一个特殊的字节来指示它是否准备好接收数据。由 Handshake.XonXoff 提供,它使用标准控制字符 Xon (Ctrl+Q) 和 Xoff (Ctrl+S)。仅适用于通信协议不在其数据中使用这些控制代码的情况。换句话说,当您传输文本而不是二进制数据时。

第三种方法是一种完全不同的方法,也很常见,您使设备仅在 PC 要求时才发送任何内容。主从协议。很容易保证接收缓冲区中有足够的空间用于响应。您在协议中指定特定命令,即 PC 发送以查询特定数据项的命令。

于 2013-06-29T13:49:25.623 回答
1

When you open a serial port for input, a buffer (queue) is automatically created to hold incoming data until it is read by your program. This buffer is typically 4096 bytes in size (although that may vary according to the version of Windows, serial port driver etc.).

A 4096-byte buffer is normally sufficient in almost all situations. At the highest standard baud rate (115200 baud) it corresponds to more than 300 msecond of storage (FIFO) first in first out, so as long as your program services the serial port at least three times a second no data should be lost. In your particular case, because you read the serial every 1 second, you may loose data if the timing and the buffered data do not match.

However in exceptional circumstances it may be useful to be able to increase the size of the serial input buffer. Windows provides the means to request an increased buffer size, but there is no guarantee that the request will be granted.

Personally I prefer to have a continuous stream of data from Arduino and decide in my c# app what to do with those data but at least I am sure I do not loose information due to limitation of the hardware involved.

Update: Playing with Arduino quite often, I also agree with the third option given by Hans in his answer. Basically your app should send to Arduino a command to get printed out (Serial.Print or Serial.Println) the data you need and be ready to read it.

于 2013-06-29T13:54:12.927 回答