SerialPort类问题

Nyr*_*yra 8 c# serial-port

我试图让串口接收正确的消息时遇到很多问题.它不断截断消息.这是我的代码,我将尝试在代码之后详细说明.

public SerialComms(SerialPort sp)
{
   this.sp = sp;
   this.sp.Open();
   this.sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);

   do
   {
      Console.WriteLine("port open waiting message");
      Console.ReadKey();
   } while(!_terminate);

   this.sp.Close();
}

void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   string dataReceived;
   StringComparer strComp = StringComparer.OrdinalIgnoreCase;
   SerialPort sp = (SerialPort)sender;
   int i = sp.BytesToRead;
   byte[] _byte = new byte[i];
   char[] _char = new char[i];
   sp.read(_byte, 0, i);
   dataReceived = Encoding.UTF8.GetString(_byte);
   //dataReceived = new string(_char);
   //dataReceived = sp.ReadExisting();

   if (strComp.Equals("00000000000000"), dataReceived))
      _terminate = true;

   Console.WriteLine(dataReceived);
}
Run Code Online (Sandbox Code Playgroud)

现在我有一个测试项目,我们用它来测试生产中使用传统软件的串行com-我知道这样运行正常.我已经将一个串行监视器连接到端口,并且通过传输发送的消息没有任何问题.当我第一次发送消息如012345678901234时,它通常会很好,在接收端,显示器显示它通过; 但是,当它打印到控制台时,它会在第一条消息后被截断.我在端口监视器和控制台输出上附加了消息的屏幕截图(显示的笑脸和心脏是正在转换的前缀字节 - 为什么它是一个心脏和笑脸我不知道)

好的,所以我不能发布图片,因为我没有足够的声誉这样做.我将在下面的控制台中写出输出的内容(在这种情况下由于某种原因它也截断了第一条消息:()

在串口监视器上,正在传输的消息如下(我发送了三次,每次消息发送之间有几秒的延迟时间):
02 31 32 33 34 35 36 37 38 39 30 31 32 33 34 03 .12345678901234 .
02 31 32 33 34 35 36 37 38 39 30 31 32 33 34 03 .12345678901234.
02 31 32 33 34 35 36 37 38 39 30 31 32 33 34 03 .12345678901234.

在控制台我收到了以下(该☺和♥字符是02和03,它们是一个STX和ETX信息是标准为我们传输):
☺123456
78901234♥

123
456
7890
123
4♥

123
456
7890
123
4 ♥

这个问题让我发疯!请帮忙!遗产是使用过时的MSCommLib,我们正在转向.Net 4

Han*_*ant 5

这在任何通信协议中都是正常和常见的.网络上的TCP也具有此属性.字节作为流传输,而不是数据包.因此,当您的DataReceived事件处理程序触发时,您只知道您有一些可用的字节.在处理之前,您需要将接收字节组合成完整的响应.

这需要一个协议,一种识别你得到完整响应的方法.你有一个,那些STX和ETX字节告诉你.特别是ETX,STX是一种过滤掉连接设备时可能获得的噪声字节的方法.

一个非常简单的方法是将NewLine属性设置为(char)3并且只调用ReadLine().

更好的方法是过滤STX帮助您消除的噪音,同时避免死锁情况:

private const int MaxResponse = 42;
private const int STX = 2;
private const int ETX = 3;
private byte[MaxResponse] response;
private int responseLength;

void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   var sp = (SerialPort)sender;
   int cnt = sp.BytesToReceive;
   for (int ix = 0; ix < cnt; ++ix) {
       byte b = (byte)sp.ReadByte();
       if (responseLength == 0 && b != STX) continue;
       if (b != ETX) response[responseLength++] = b;
       else {
           var str = Encoding.ASCII.GetString(response, 0, responseLength);
           HandleResponse(str);
           responseLength = 0;
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

并编写HandleResponse()方法来处理您收到的数据.