问题描述
我在尝试让串行端口接收正确消息时遇到很多问题.它不断截断消息.这是我的代码,我会在代码之后详细说明.
I am having a lot of issues trying to get a serial port to receive the correct message. It keeps truncating the messages. Here is my code and I will try to elaborate after the code.
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);
}
现在我有一个测试项目,我们用它来测试我们在生产中使用旧版软件的串行通信 - 我知道它运行良好.我已将串行监视器连接到端口,并且通过传输的消息没有任何问题.当我第一次发送诸如012345678901234之类的消息时,通常可以正常通过,而在接收端,监视器显示它已通过;但是,当它打印到控制台时,它会在第一条消息后被截断.我附上了在端口监视器和控制台输出上通过的消息的屏幕截图(出现的笑脸和心是被转换的前缀字节 - 为什么它是心和笑脸,我不知道)
Now I have a test project that we use for testing our serial coms in production with legacy software- I know this runs fine. I have attached a serial monitor to the port and the message coming through transmits without any issues. When I send a message such as 012345678901234 the first time through it usually goes through just fine, and on the receiving end, the monitor shows it coming through; however, when it prints to the console it gets truncated after the first message. I am attaching screenshots of the message going through on the port monitor and the console output (the smiley face and heart that show up are the prefix bytes being converted- why it is a heart and a smiley face I have no idea)
好的,所以我不能发布图片,因为我没有足够的声誉来这样做.我将在下面的控制台中写入输出的样子(在这种情况下,由于某种原因,它也截断了第一条消息:()
Ok so I can't post the image because of the fact that I do not have enough reputation to do so. I will write what the output looks like to the console below (in this case for some reason it truncated the first message as well :( )
在串口监视器上,正在传输的消息如下(我发送了三次,每次发送消息之间有几秒钟的延迟时间"):
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.
On the serial port monitor the message being transmitted is as follows (I sent it three times with a few seconds 'lag time' between each message send):
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♥
On the console I received the following (The ☺ and ♥ characters are 02 and 03, they are an STX and ETX message that is standard for our transmissions):
☺123456
78901234♥
☺
123
456
7890
123
4♥
☺
123
456
7890
123
4♥
这个问题快把我逼疯了!!!请帮忙!遗留问题是使用过时的 MSCommLib,我们正在迁移到 .Net 4
This issue is driving me mad!!! Please help! The legacy is using the outdated MSCommLib and we are moving to .Net 4
推荐答案
这在任何通信协议中都是完全正常和常见的.网络上的 TCP 也具有此属性.字节作为 流 传输,而不是数据包.因此,当您的 DataReceived 事件处理程序触发时,您只知道您有 一些 字节可用.您可以在处理之前将接收字节组装成完整的响应.
This is entirely normal and common in any communication protocol. TCP over a network has this property as well. Bytes are transferred as a stream, not a packet of data. So when your DataReceived event handler fires, you only know that you have some bytes available. It is up to you to assemble the receive bytes into a complete response before you process it.
这需要一个协议,这是一种识别您得到完整响应的方法.你有一个,那些 STX 和 ETX 字节告诉你.特别是 ETX,STX 是一种过滤掉连接设备时可能收到的噪声字节的方法.
This requires a protocol, a way to recognize that you got a full response. You have one, those STX and ETX bytes tell you. ETX in particular, the STX is a way to filter out noise bytes that you might get when you connect the device.
一个非常简单的方法是将 NewLine 属性设置为 (char)3
并调用 ReadLine().
A very simple way to get it going is to set the NewLine property to (char)3
and just call ReadLine().
更好的方法是同时过滤 STX 帮助您消除的噪音,同时避免死锁情况:
A better way to do this is to also filter the noise that STX helps you to eliminate, also avoids a deadlock scenario:
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;
}
}
}
并编写 HandleResponse() 方法来处理收到的数据.
And write the HandleResponse() method to process the data you received.
这篇关于SerialPort 类问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!