从C#中的串口读取

我已经尝试过使用Readline()并且数据被删除,我尝试使用Read()但是我不知道如何使用它的错误validation方法,因为我可能会一个接一个地获得几个数据包而我无法知道将会有另一个数据包进入。在数据包BytesToRead之间是0,所以我不能使用它。 当读取数据到缓冲区时你有一个定时器或让线程进入hibernate状态以允许所有数据包到达?

我搞不清楚了。 不知道下一步该尝试什么。

我应该提一下,我不能保证从串口发出的字符串将以\ n或\ r或\ r \ n结束。 当用户按下PRINT时,我只需要一种简单的方法来读取将来自秤的所有数据包。

有人在这里回答了我喜欢的想法 – 等待所有数据包的一定时间,但他们删除了他们的答案。 你有可能重新发布它吗?

您是否尝试过收听SerialPort类的DataRecieved事件?

 public class MySerialReader : IDisposable { private SerialPort serialPort; private Queue recievedData = new Queue(); public MySerialReader() { serialPort = new SerialPort(); serialPort.Open(); serialPort.DataReceived += serialPort_DataReceived; } void serialPort_DataReceived(object s, SerialDataReceivedEventArgs e) { byte[] data = new byte[serialPort.BytesToRead]; serialPort.Read(data, 0, data.Length); data.ToList().ForEach(b => recievedData.Enqueue(b)); processData(); } void processData() { // Determine if we have a "packet" in the queue if (recievedData.Count > 50) { var packet = Enumerable.Range(0, 50).Select(i => recievedData.Dequeue()); } } public void Dispose() { if (serialPort != null) serialPort.Dispose(); } 

我们前一段时间经历了同样的过程。

读取“数据包”的唯一方法是有一些关于它们的开始和结束位于流中的概念。

来自msdn :

因为SerialPort类缓冲数据,并且BaseStream属性中包含的流没有,所以两者可能会争用可读取的字节数。 BytesToRead属性可以指示有要读取的字节,但BaseStream属性中包含的流可能无法访问这些字节,因为它们已缓冲到SerialPort类。

我们使用了一个backround线程(你可以使用BackgroundWorker)将数据读入缓冲区。 如果你不能使用SerialPort.Newline属性可靠地设置终止字符(因为它会变化!)那么你将需要实现自己的数据包检测系统,因为你无法使用阻塞的SerialPort.Readline()方法。

您可以使用SerialPort.Read()(或使用SerialPort.ReadExisting()方法的字符串)读入字节缓冲区,并在检测到数据中的有效数据包时生成事件。 请注意,Read()(我假设ReadExisting())清空了SerialPort的缓冲区,因此您需要将数据保存在其他位置。

如果设置SerialPort.ReadTimeout,则可以处理TimeoutException,并可以轻松处理设备未传输的情况。 如果您使用固定数量的字节或其他一些非终止方案,这是重置数据包检测的好方法。 (如果不需要部分数据包,请在超时时使用SerialPort.DiscardInBuffer())。

祝好运

由于字节可能随时进入,因此缓冲传入数据至关重要。 所以你应该

  1. 缓冲传入的数据
  2. 扫描缓冲区以查找完整数据
  3. 从缓冲区中删除使用过的数据

我只是想知道你是否仍然遇到串口问题。 如果是这样,我在C#中开发了一种串口编程语言,我相信它几乎可以解决每个人遇到的所有问题。

请你试试看吧? 例如; 您可以缓冲来自串行端口的传入数据,如下所示,并轻松执行字符串操作。

 state Init // define a global variable our $BUFFER = ""; jump(Receive); end state state Receive recv(); $len = length($DATA_PACKET); if("$len > 0") { $BUFFER += $DATA_PACKET; call(Parser); } end state state Parser // check if buffer matchs regular expression pattern if(match($BUFFER, "(?.*?(?.*?)(?[0-9A-F]{2}))")) { // Received complete data $lenData = length($WILLDELETE); $BUFFER = remove($BUFFER, 0, $lenData); // Do operations with the other parsed fields. $DATA and $CHECKSUM in this example. } end state 

项目可以在sourceforge上免费获得,如果您有任何疑问,请随时提出。

项目主页

下载链接