从串行数据数组中解码和重新格式化值
Posted
技术标签:
【中文标题】从串行数据数组中解码和重新格式化值【英文标题】:Decode and reformat values from Serial data array 【发布时间】:2021-03-04 17:14:39 【问题描述】:我的应用程序从串行接口接收数据。有些接收到的记录可以直接显示到文本框,有些则必须转换。我必须解码的一个串行消息包含 512 字节和多个信息。
接收我使用的数据:
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
var serialPort = (SerialPort)sender;
string data = serialPort.ReadExisting();
dataDecoder(data);
在数据解码器中,我执行以下操作:
private void dataDecoder(string input)
string post = ""; //empty string
char[] buf = input.ToCharArray(); //Converter input String to Char Array
if (buf[0] == '#') //only process records starting with #, others go directly to SetText(string)
post += "Decode, Len="; //Informal message
int up = int.Parse(buf[2].ToString()); //Upper byte of 16bit-binary integer
int low = int.Parse(buf[3].ToString()); //lower byte of 16bit-binary integer
int len = low << 8 | up; //converter to decimal int
post += len; //edit string
post += " Channel: "; //informal message
int first = int.Parse(buf[4].ToString()); //Upper byte of 16bit-binary integer
int second = int.Parse(buf[5].ToString()); //lower byte of 16bit-binary integer
int chnl = second << 8 | first; //converter to decimal int
post += chnl; //edit string
post += "DATA"; //informal message
for (int i = 0; i < 507; i++) //decode contents 6 to 511 (512byte is checsum)
int k = i + 6; //format selector
int one = int.Parse(buf[k].ToString()); //Highest byte of 32bit-binary integer
int two = int.Parse(buf[k + 1].ToString()); //second high byte of 32bit-binary integer
int three = int.Parse(buf[k + 2].ToString()); //second low byte of 32bit-binary integer
int four = int.Parse(buf[k + 3].ToString()); //lowest byte of 32bit-binary integer
int rec = four << 24 | three << 16 | two << 8 | one; //convert to decimal int
post += rec; //edit string
post += ","; //separation character
SetText(post); //set text to texbox
else
SetText(input); //set input to textbox (unconverted)
Build 不会报告任何错误或警告。但是当我运行代码并到达这个函数时,程序确实会因消息而崩溃
System.FormatException: '输入字符串的格式不正确。'
上线
int up = int.Parse(buf[2].ToString());
我可以做些什么来更好地解决这个问题?
编辑 这是串行数据的第一部分(取自串行监视器)
23 42 FC 01 00 00 00 00 00 00 00 00 00 00 00 00
23 是# 42是B FC 01 是记录长度,在这种情况下是已知的,它的 508 (01FC)
【问题讨论】:
【参考方案1】:我不知道你有什么数据格式,但你可以使用正则表达式或自定义映射,如下所示。
public static unsafe void dataDecoder(string input)
switch (input[0])
case '#':
byte[] bytes = Encoding.UTF8.GetBytes(input);
Map(bytes);
break;
public static unsafe string Map(this byte[] bytes)
var offset = 2;
var post = string.Empty;
if (bytes == null)
return post;
//while (bytes.Length < offset)
int len =0
int chnl =0;
fixed (byte* numPtr = &bytes[offset])
len = *(Int16*)numPtr;
offset += 2;
post += len;
post += " Channel: ";
fixed (byte* numPtr = &bytes[offset])
chnl = *(Int16*)numPtr;
offset += 2;
// etc...
return post;
【讨论】:
“占用一个字符”是什么意思? char 在 C# 中可以是 16 位,而 int 是 32 位,所以我认为它不能更大。您还使用了我之前尝试过的字符串 [0],但我已经阅读了无法在 C# 中完成的帖子,因为字符串是不可变的。 您可以使用不安全的代码并通过指针读取数据,如示例。首先我们跳过第一个字节'#',第二个得到 len Int16 这将是你的长度:固定 (byte* numPtr = &bytes[2]) len = (Int16)numPtr; 我的意思是 Int16 可以占用 2 个字节 (FF FF),或者如果存储在 5 个字节 '32767' 的字符串表示形式中 - ASCII以上是关于从串行数据数组中解码和重新格式化值的主要内容,如果未能解决你的问题,请参考以下文章