SerialPort读取STX直到ETX

时间:2019-12-10 10:10:25

标签: c# serial-port

我是C#开发的新手。我正在通过阅读我的串行端口使用以下代码:

var mySerialPort = new SerialPort("Com3");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;

mySerialPort.Open();
mySerialPort.DataReceived += new 
SerialDataReceivedEventHandler(DataReceivedHandler);

 private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
 {
     SerialPort sp = (SerialPort)sender;
     string tmp = sp.ReadLine();
 }

问题在于,tmp始终为空。可能是它试图找到CR LF。 我的串行端口设备发送了以下行:

STX(   0.000CRETX

我是否可以更改尝试读取readline的最后一个字符的选项? 因此,每次读取ETX都返回我的字符串。

4 个答案:

答案 0 :(得分:0)

ReadLine的行为非常严格。

例如,当我从Arduino串行端口读取时,我倾向于使用它:

byte[] buffer = new byte[sp.BytesToRead];
sp.Read(buffer, 0, buffer.Length);

您还可以将读数拆分到其自己的线程中,该线程仅读取字节,直到其具有完整的行为止,然后将其排队以供主线程处理。最有可能对您的应用程序造成过大杀伤力。

答案 1 :(得分:0)

我不建议这样做,但是您应该可以使用此属性进行设置。

SerialPort.NewLine Property

  

获取或设置用于解释对ReadLine()WriteLine(String)方法的调用结束的值。

相反,最好使用Read()读取字节数组,并将数据格式检查为@omglolbah的答案。

这是您的决定,因此请您自担风险。

答案 2 :(得分:0)

ReadLine和.NET SerialPort的其他部分一样都损坏。 请查看下面的链接以获取正确的实现:

https://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport#comment-9986 https://www.sparxeng.com/blog/software/reading-lines-serial-port

基本上可以归结为:

byte[] buffer = new byte[blockLimit];
Action kickoffRead = null;
kickoffRead = delegate {
port.BaseStream.BeginRead(buffer, 0, buffer.Length, delegate (IAsyncResult ar) {
    try {
        int actualLength = port.BaseStream.EndRead(ar);
        byte[] received = new byte[actualLength];
        Buffer.BlockCopy(buffer, 0, received, 0, actualLength);
        raiseAppSerialDataEvent(received);
    }
    catch (IOException exc) {
        handleAppSerialError(exc);
    }
    kickoffRead();
}, null);
};
kickoffRead();

答案 3 :(得分:0)

我认为您很亲近,您只需要意识到DataReceived事件在某种程度上随机触发。它可能在消息中间触发,而您只能得到消息的一半。因此,您必须构建自己的字符串,并使用ETX字符表示您已收到整个消息。请勿混淆NewLine属性,在下面的示例中使用ReadExisting时就不需要这样做。

char ETX = (char)4;
StringBuilder sb = new StringBuilder();
string currentLine = string.Empty;

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    string Data = serialPort1.ReadExisting();

    foreach (char c in Data)
    {
        if (c == ETX)
        {
            sb.Append(c);

            CurrentLine = sb.ToString();
            sb.Clear();

            //parse CurrentLine here or print it to textbox
            //note you might have to invoke because this event is on its own thread
        }
        else
        {
            sb.Append(c);
        }
    }
}

此外,在打开端口之前,请创建您的DataReceived事件。使用完配置后对它进行更改是不好的。

mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
mySerialPort.Open();