我可以很容易地从设备接收数据的响应,并使用Serial.ReadExisting()在文本框中显示它。显示数据时,问题出在一些控制字符(ACK、SOH、ETX等)无法打印。
我尝试用下面的代码从串行响应中检测控制字符,但在比较中出现了一些错误。
代码是:
public bool read_port(ref string rs232data, int timeout)
{
try
{
int index_read = 0;
int total_read = 0;
int i = 0;
int delay_ms = 1;
byte[] buffer = new byte[serialPort1.ReadBufferSize];
rs232data = "";
string buffer_str = "";
if ((serialPort1.IsOpen == false))
{
#if DEBUG
MessageBox.Show("COM port is not opening");
#endif
return false;
}
do
{
Application.DoEvents();
PauseForMilliSeconds(delay_ms); //System.Threading.Thread.Sleep(delay_ms);
i++;
//serial port receive data
if (serialPort1.BytesToRead <= 0) continue;
if (i > 1) i--;
index_read = serialPort1.Read(buffer, total_read, serialPort1.BytesToRead);
total_read += index_read;
buffer_str = ToStringLsb(buffer);
//// Find a Start byte
int ack_index = buffer_str.LastIndexOf(ToStringLsb(ACK));
int nak_index = buffer_str.LastIndexOf(ToStringLsb(NAK));
//Find a Stop byte
int stop_index_etx = buffer_str.LastIndexOf(ToStringLsb(ETX));
int stop_index_lf = buffer_str.LastIndexOf(ToStringLsb(LF));
if ((stop_index_etx < 0) && (stop_index_lf < 0) && (ack_index < 0)) continue; // Can't find a byte Stop
if (stop_index_etx > 0)
{
if ((stop_index_etx + 1) < total_read)
{
stop_index_etx++;
}
else
{
if (buffer[total_read - 2] == ETX)
{
stop_index_etx--;
}
else continue;
}
}
rs232data = buffer_str.Substring(0, total_read);
return true;
}
while (i < timeout);
return false;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return false;
}
}
public static string ToStringLsb(byte bytevalue)
{
try
{
byte[] bytearray = { bytevalue };
return System.Text.Encoding.GetEncoding("iso-8859-1").GetString(bytearray);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
return "";
}
}
public static string ToStringLsb(byte[] bytearray)
{
return System.Text.Encoding.GetEncoding("iso-8859-1").GetString(bytearray);
}发布于 2019-04-27 00:13:55
您需要查看ASCII映射,并确定哪些值是您要查找的控制值。

例如,我将在代码中定义以下控制字符,然后您可以在DataReceived事件中查找这些字符。
char ACK = (char)6;
char NAK = (char)21;
char SOH = (char)1;
char LF = (char)10;
StringBuilder sb = new StringBuilder();
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string Data = serialPort1.ReadExisting();
foreach (char c in Data)
{
if (c == LF)
{
sb.Append(c);
CurrentLine = sb.ToString();
sb.Clear();
//parse CurrentLine here or print it to textbox
}
if (c == ACK)
{
sb.Append("<ACK>"); //or whatever you want to print
}
else
{
sb.Append(c);
}
}
}编辑:在下面的评论中回答你的一些问题。当DataReceived事件在其缓冲区中获取字符时会触发,但它可以在仅获取消息的一半时触发。所以当使用这个事件时,你必须构建一个字符串,直到你知道你得到了整个消息。在上面的例子中,我假设LF (换行符)表示我有完整的消息。对于您来说,您可以使用您正在搜索的任何标志消息结束的字符(在您的情况下可能是ACK?)。您可以选择是否将该字符附加到字符串中,这取决于您的要求。在我的例子中,你可以看到我附加了LF,但是你可以很容易地去掉这一行。
https://stackoverflow.com/questions/55860487
复制相似问题