从串行数据数组中解码和重新格式化值

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

以上是关于从串行数据数组中解码和重新格式化值的主要内容,如果未能解决你的问题,请参考以下文章

JSON 可解码嵌套数组具有不同的格式和类型

Verilog学习(13)PLL与搜索代码

如何从数据库特定的选定值添加到解码的 Json 数组

如何看rmvb格式视频的分辨率和解码值?

重新格式化地图值并使用扩展语法进行更新

将值附加到存储在 MySQL 中的 JSON 解码数组参数