为什么计算出的校验和与通过串行端口发送的 BCC 不匹配?
我有一个用 C# 编写的小应用程序,它侦听串行端口以获取传入的信息。信息的形式如下: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:我还没有弄清楚这一点,并且我得到了更多结果完全不一致的测试数据(我发送校验和的数量每次都不同,没有模式)。感觉就像我只是计算了错误的校验和,但我不知道如何计算。
I've got a little application written in C# that listens on a SerialPort for information to come in. The information comes in as: STX + data + ETX + BCC
. We then calculate the BCC of the transmission packet and compare. The function is:
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);
}
And it seems to work more or less. It is accurately not including the STX or the BCC and accurately including the ETX in it's calculations. It seems to work a very large percentage of the time, however we have at least two machines we are running this on, both of which are Windows 2008 64-bit in which the BCC calculation NEVER adds up. Pulling from a recent log I had in one byte 20 was sent and I calculated 16 and one where 11 was sent and I calculated 27.
I'm absolutely stumped as to what is going on here. Is there perhaps a 64 bit or Windows 2008 "gotcha" I'm missing here? Any help or even wild ideas would be appreciated.
EDIT:
Here's the code that reads the data in:
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);
}
And the DataReceived()
function takes that string and appends it to global StringBuilder
object. It then stays as a string builder until it's passed to these various functions at which point the .ToString()
is called on it.
EDIT2: Changed the code to reflect my altered routines that operate on bytes/byte arrays rather than strings.
EDIT3: I still haven't figured this out yet, and I've gotten more test data that has completely inconsistent results (the amount I'm off of the send checksum varies each time with no pattern). It feels like I'm just calculating the checksum wrong, but I don't know how.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
缓冲区被定义为字符串。虽然我怀疑您正在传输的数据是字节。我建议使用字节数组(即使您发送的是 ascii/utf/任何编码)。然后校验和有效后,将数据转换为字符串
The buffer is defined as a String. While I suspect the data you are transmitting are bytes. I would recommend using byte arrays (even if you are sending ascii/utf/whatever encoding). Then after the checksum is valid, convert the data to a string
计算BCC不是标准的,而是“客户定义的”。我们为客户编写接口,多次发现不同的算法,包括求和、异或、掩码、分离 stx、etx 或两者,或分离所有已知字节。例如,包结构是“stx,机器代码,命令代码,数据,...,数据,etx,bcc”,bcc的演算是(客户指定!)作为“从命令代码到所有字节的二进制和”最后的数据,包括在内,并且全部用 0xCD 屏蔽”。也就是说,我们首先要添加所有未知字节(添加 stx、etx 或机器代码是没有意义的,如果这些字节不匹配,无论如何该帧都会被丢弃!它们的值在获取时进行测试,以确保帧正确开始、结束,并且它被发送到接收机器,在这种情况下,我们必须仅密送帧中可以更改的字节,这将减少时间,因为在许多情况下我们使用4 或 8 位慢速微控制器,请注意,这是对字节求和,而不是对它们进行异或,这只是一个示例,其他客户想要其他东西),其次,在我们得到总和之后(如果是,则可以是 16 位)在加法过程中没有被截断),我们用密钥(在本例中为 0xCD)对其进行掩码(按位与)。这种东西经常用于各种封闭系统,例如 ATM(将串行键盘连接到 ATM),出于保护原因等,以及加密和其他方面的考虑。因此,您确实必须检查(读“破解”)您的两台机器如何计算其(非标准)BCC。
computing BCC is not standard, but "customer defined". we program interfaces for our customers and many times found different algorithms, including sum, xor, masking, letting apart stx, etx, or both, or letting apart all known bytes. for example, package structure is "stx, machine code, command code, data, ..., data, etx, bcc", and the calculus of bcc is (customer specified!) as "binary sum of all bytes from command code to last data, inclusive, and all masked with 0xCD". That is, we have first to add all the unknown bytes (it make no sense to add stx, etx, or machine code, if these bytes do not match, the frame is discarded anyhow! their value is tested when they are got, to be sure the frame starts, ends correctly, and it is addressed to the receiving machine, and in this case, we have to bcc only the bytes that can change in the frame, this will decrease the time, as in many cases we work with 4 or 8 bit slow microcontrollers, and caution, this is summing the bytes, and not xoring them, this was just an example, other customer wants something else), and second, after we have the sum (which can be 16 bits if is not truncated during the addition), we mask it (bitwise AND) with the key (in this example 0xCD). This kind of stuff is frequently used for all kind of close systems, like ATM's for example (connecting a serial keyboard to an ATM) for protection reasons, etc., in top of encryption and other things. So, you really have to check (read "crack") how your two machines are computing their (non standard) BCC's.
确保您已将端口设置为在端口设置代码中的某处接受空字节。 (这可能是默认值,我不确定。)
此外,检查到达串行端口的字节类型,并仅接受数据:
Make sure you have the port set to accept null bytes somewhere in your port setup code. (This maybe the default value, I'm not sure.)
Also, check for the type of byte arriving at he serial port, and accept only data: