1

我有一个用 C# 编写的小应用程序,它在 SerialPort 上侦听以获取信息。信息以:STX + data + ETX + BCC. 然后我们计算传输数据包的 BCC 并进行比较。功能是:

private bool ConsistencyCheck(byte[] buffer)
{
    byte expected = buffer[buffer.Length - 1];
    byte actual = 0x00;

    for (int i = 1; i < buffer.Length - 1; i++)
    {
        actual ^= buffer[i];
    }

    if ((expected & 0xFF) != (actual & 0xFF))
    {
        if (AppTools.Logger.IsDebugEnabled)
        {
            AppTools.Logger.Warn(String.Format("ConsistencyCheck failed: Expected: #{0} Got: #{1}", expected, actual));
        }
    }

    return (expected & 0xFF) == (actual & 0xFF);
}

它似乎或多或少地起作用。它准确地不包括 STX 或 BCC,并且准确地将 ETX 包括在其计算中。它似乎大部分时间都在工作,但是我们至少有两台机器正在运行它,这两台机器都是 Windows 2008 64 位,其中 BCC 计算永远不会累加。从最近的日志中提取一个字节 20 被发送,我计算出 16 和一个 11 被发送的地方,我计算出 27。

我对这里发生的事情感到非常困惑。我在这里是否缺少 64 位或 Windows 2008“陷阱”?任何帮助甚至疯狂的想法都将不胜感激。

编辑:

这是读取数据的代码:

private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    // Retrieve number of bytes in the buffer
    int bytes = serialPort.BytesToRead;

    // Create a byte array to hold the awaiting data
    byte[] received = new byte[bytes];

    //read the data and store it
    serialPort.Read(received, 0, bytes);

    DataReceived(received);
}

DataReceived()函数获取该字符串并将其附加到全局StringBuilder对象。然后它一直作为一个字符串构建器,直到它被传递给这些不同的函数,此时它.ToString()被调用。

EDIT2:更改了代码以反映我更改的对字节/字节数组而不是字符串进行操作的例程。

EDIT3:我还没有弄清楚这一点,而且我得到了更多结果完全不一致的测试数据(发送校验和的数量每次都不同,没有模式)。感觉就像我只是在计算校验和错误,但我不知道如何。

4

3 回答 3

2

缓冲区被定义为一个字符串。虽然我怀疑您传输的数据是字节。我建议使用字节数组(即使您发送的是 ascii/utf/whatever 编码)。然后校验和有效后,将数据转换为字符串

于 2009-10-09T19:12:14.953 回答
1

计算 BCC 不是标准的,而是“客户定义的”。我们为客户编写接口,并多次发现不同的算法,包括求和、异或、屏蔽、分开 stx、etx 或两者,或分开所有已知字节。例如,包结构是“stx, machine code, command code, data, ..., data, etx, bcc”,bcc的演算是(客户指定!)为“从命令代码到所有字节的二进制和最后一个数据,包括在内,并且全部用 0xCD 屏蔽”。也就是说,我们首先要添加所有未知字节(添加stx,etx或机器码是没有意义的,如果这些字节不匹配,则无论如何丢弃帧!他们的值在获得时进行测试,以确保帧正确开始、结束,并且发送到接收机器,在这种情况下,我们必须只密送帧中可以更改的字节,这将减少时间,因为在许多情况下我们使用 4 位或 8 位慢速微控制器,请注意,这是对字节求和,而不是对它们进行异或运算,这是只是一个例子,其他客户想要别的东西),其次,在我们得到总和之后(如果在加法过程中没有截断,它可以是 16 位),我们用密钥(在本例中为 0xCD)屏蔽它(按位与) . 这种东西经常用于所有类型的封闭系统,例如 ATM(将串行键盘连接到 ATM)出于保护原因等等,除了加密和其他事情。所以,你真的必须检查(阅读“破解”)你的两台机器是如何计算他们的(非标准的)密件抄送的。因为在许多情况下,我们使用 4 位或 8 位慢速微控制器,请注意,这是对字节求和,而不是对它们进行异或运算,这只是一个示例,其他客户想要别的东西),其次,在我们得到总和之后(如果在加法过程中没有被截断,它可以是 16 位),我们用密钥(在本例中为 0xCD)屏蔽它(按位与)。这种东西经常用于所有类型的封闭系统,例如 ATM(将串行键盘连接到 ATM)出于保护原因等等,除了加密和其他事情。所以,你真的必须检查(阅读“破解”)你的两台机器是如何计算他们的(非标准的)密件抄送的。因为在许多情况下,我们使用 4 位或 8 位慢速微控制器,请注意,这是对字节求和,而不是对它们进行异或运算,这只是一个示例,其他客户想要别的东西),其次,在我们得到总和之后(如果在加法过程中没有被截断,它可以是 16 位),我们用密钥(在本例中为 0xCD)屏蔽它(按位与)。这种东西经常用于所有类型的封闭系统,例如 ATM (将串行键盘连接到 ATM)出于保护原因等等,除了加密和其他事情。所以,你真的必须检查(阅读“破解”)你的两台机器是如何计算他们的(非标准的)密件抄送的。在我们得到总和(如果在加法过程中没有被截断,它可以是 16 位)之后,我们用密钥(在本例中为 0xCD)屏蔽它(按位与)。这种东西经常用于所有类型的封闭系统,例如 ATM (将串行键盘连接到 ATM)出于保护原因等等,除了加密和其他事情。所以,你真的必须检查(阅读“破解”)你的两台机器是如何计算他们的(非标准的)密件抄送的。在我们得到总和(如果在加法过程中没有被截断,它可以是 16 位)之后,我们用密钥(在本例中为 0xCD)屏蔽它(按位与)。这种东西经常用于所有类型的封闭系统,例如 ATM (将串行键盘连接到 ATM)出于保护原因等等,除了加密和其他事情。所以,你真的必须检查(阅读“破解”)你的两台机器是如何计算他们的(非标准的)密件抄送的。

于 2011-04-20T07:02:13.780 回答
0

确保您已将端口设置为在端口设置代码中的某处接受空字节。(这可能是默认值,我不确定。)

port.DiscardNull = false;

此外,检查到达串行端口的字节类型,并仅接受数据:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    if (e.EventType == SerialData.Chars)
    {
        // Your existing code
    }
}
于 2009-10-10T09:42:58.487 回答