6

我试图搜索我的问题的重复项,但找不到。另外,很抱歉标题不太好理解。我对我正在搜索的内容以及术语感到非常困惑。我是一名电子工程师,对 .Net 框架知之甚少,所以请善待我 :)

我目前的项目是一个心率监测器,可以将测量的心率存储到 EEPROM 中,然后发送到 PC 以供以后查看日志。

我正在使用 RS-232(串行)协议与 8 位微控制器连接。每当我向微控制器发送一个l代表charlog的信息时,它都会以以下格式向我发送一些信息:

0x1E 0x21 0x01 0x13 0x14 0x35 0x46 0x1E 0x21 0x01 0x13 0x14 0x43 0x48 0x0A 0x0D

空格用于提供信息,这些字节彼此不分隔。

从微控制器发送的这些 8 位 HEX 值包括记录信息的开始,即0x1EDD MM YY HH MM 格式的日期和时间以及记录的心率。当所有记录都回显时,将发送 0x0A 和 0x0D 字符。

例如,上面的代码意味着:

Record start.
21.01.13 14:35
Heart Rate: 70
Record start.
21.01.13 14:43
Heart Rate: 72
End of records.

我怎样才能得到这样的字符串值:“S210113143570S210113144372”,哪里S可以是任何东西。之后,我将对其应用正则表达式语法并将其划分为组,以便我可以将这些值添加到listview控件中。

在评论和答案后编辑:

我没有写错样本。不幸的是,编码与上面完全相同。

4

4 回答 4

5

所以,实际上每个字节代表一个数字。我假设你已经有一个byte[]包含这些值的数组:

var data = new byte[] { 0x1E, 0x21, 0x01, 0x13, 0x14, 0x35, 0x46,
                        0x1E, 0x21, 0x01, 0x13, 0x14, 0x43, 0x48, 0x0A, 0x0D };

你现在可以像这样创建真实的对象:

class LogEntry
{
    public DateTime Timestamp { get; set; }
    public int HeartRate { get; set; }
}

var logEntries = new List<LogEntry>();

for(int i = 0; i < data.Length; i+= 7)
{
    if(data[i] == 0x0a && data[i + 1] == 0x0d)
        break;
    if(data[i] != 0x1e)
        throw new InvalidDataException();

    var logEntry = new LogEntry();
    var year = BcdToDecimal(data[i + 3]) + 2000;
    var month = BcdToDecimal(data[i + 2]);
    var day = BcdToDecimal(data[i + 1]);
    var hour = BcdToDecimal(data[i + 4]);
    var minute = BcdToDecimal(data[i + 5]);
    var heartRate = data[i + 6];
    logEntry.Timestamp = new DateTime(year, month, day, hour, minute, 0);
    logEntry.HeartRate = heartRate;
    logEntries.Add(logEntry);
}

byte BcdToDecimal(byte bcdValue)
{
    return (byte)((bcdValue / 16 * 10) + (bcdValue % 16));
}

该方法BcdToDecimal将 BCD 转换为其实际值。

于 2013-01-21T12:22:01.603 回答
0

兄弟,我认为您应该考虑使用字符串,即

string heartRate=70;
string recordStart=21.01.13 14:35;
string fullValue = heartRate + '|' + recordStart;

现在,您可以使用拆分方法轻松拆分该字符串,而不是应用正则表达式,例如,

string splittedValues[]=fullValue.Split('|');

你会在需要时得到这些值,比如

splittedValues[0] \\it will be heard rate string (at index zero)
similarly
splittedValues[1] \\it will be record start string (at index one)

我仍然不明白你的问题,如果我的回答无关紧要,请告诉我,我会澄清

于 2013-01-21T12:22:11.350 回答
0
public static String ParseData(String data)
{
    MatchCollection matches = Regex.Matches(data, "0[xX]([a-fA-F0-9]{2})");

    Int32 count = 0;
    String result = String.Empty;

    foreach (Match match in matches)
    {
        switch (count)
        {
            case 0:
            {
                if (match.Value.Equals("0x1E", StringComparison.OrdinalIgnoreCase))
                {
                    result += "S";
                    break;
                }

                goto End;
            }

            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                result += match.Groups[1].Value;
                break;

            case 6:
                result += Int32.Parse(match.Groups[1].Value, NumberStyles.HexNumber).ToString();
                count = -1;
                break;
        }

        ++count;
    }

    End:;

    return result;
}
于 2013-01-21T13:14:26.887 回答
0

我很抱歉我犯了一个非常愚蠢的错误。我看到在微控制器端执行此操作非常容易,而且不那么耗费时钟周期。现在我已经这样做了,现在解析这些值真的很容易。

我在微控制器端使用了这个例程:

unsigned char BCDtoDecimal(unsigned char bcd_number)
{
  return ((bcd_number>>4)*10 + (bcd_number&0x0F));
}

因此,代码在 C# 方面非常简单:

    private void buttonGetLogs_Click(object sender, EventArgs e)
    {
        string inputBuffer;
        char[] charArray;
        try
        {
            serialPort.Write("l");
            inputBuffer = serialPort.ReadLine();
            charArray = inputBuffer.ToCharArray();
            inputBuffer = string.Empty;
            foreach (char item in charArray)
            {
                inputBuffer += Convert.ToInt32(item).ToString();
            }
        }
        catch (Exception) { }
    }
于 2013-01-21T13:49:25.747 回答