我有这个C代码块,我不能为我的生活理解.我需要为我发送给该方法的某个字节数组计算CRC-16,它应该给出msb(最高有效字节)和lsb(最低有效字节).我还获得了一个C编写的应用程序来测试一些功能,该应用程序还为我提供了发送内容和通过COM端口接收的内容的日志.
有点奇怪的是,我输入了我在日志中找到的这个在线计算器的十六进制字符串,但它给了我不同的结果.
我把这个方法翻译成C#,但我不明白某些方面:
这是代码块:
unsigned short CalculateCRC(unsigned char* a_szBufuer, short a_sBufferLen)
{
unsigned short usCRC = 0;
for (short j = 0; j < a_sBufferLen; j++)
{
unsigned char* pucPtr = (unsigned char*)&usCRC;
*(pucPtr + 1) = *(pucPtr + 1) ^ *a_szBufuer++;
for (short i = 0; i <= 7; i++)
{
if (usCRC & ((short)0x8000))
{
usCRC = usCRC << 1;
usCRC = usCRC ^ ((ushort)0x8005);
}
else
usCRC = usCRC << 1;
}
}
return (usCRC);
}
Run Code Online (Sandbox Code Playgroud)
这是我转换为字节数组并发送到方法的十六进制字符串:02 00 04 a0 00 01 01 03
这是应该从CRC演算中得出的结果:06 35
我给出的文件说这是整个数据的CRC16 IBM(msb,lsb).
有人可以帮忙吗?我已经坚持了一段时间了.
任何代码大师都能够将C方法转换为C#?显然我不具备这样的资源.
首先,请注意,与C相比,^运算符意味着按位异或.
- 什么是pucPTR在那里做(它不是在其他地方使用)?
- 2行代码是什么意思,第一行是什么?
通过它的外观导致错误.它仅用于获取FCS的两个字节中的一个,但代码是以依赖于endianess的方式编写的.
在处理校验和算法时,Endianess非常重要,因为它们最初是为硬件移位寄存器设计的,它们首先需要MSB,即大端.另外,CRC通常意味着数据通信,并且数据通信意味着发送方,协议和接收方之间可能具有不同的字节顺序.
我猜这个代码只是为小端机器编写的,目的是用ms字节进行异或.代码指向第一个字节,然后使用+1指针算法到达第二个字节.更正后的代码应该类似于:
uint8_t puc = (unsigned int)usCRC >> 8;
puc ^= *a_szBufuer;
usCRC = (usCRC & 0xFF) | ((unsigned int)puc << 8);
a_szBufuer++;
Run Code Online (Sandbox Code Playgroud)
对unsigned int的强制转换可以通过隐式整数提升来防止意外事件.
- 为什么在第二个短的"i"是<= 7,不应该<= 8?
我认为这是正确的,但更可读的是它可以写成i < 8.
- if语句中的最后一行意味着usCRC实际上是ushort 8005?
不,这意味着用多项式0x8005对您的FCS进行异或.看到这个.
我给出的文件说这是CRC16 IBM
是的它有时被称为.虽然我记得,"CRC16 IBM"也涉及到最终结果的一些反转(?).我仔细检查一下.
总的来说,请小心这段代码.无论谁编写它,都没有太多关于endianess,整数签名和隐式类型促销的线索.这是业余级代码.您应该能够在网上找到相同CRC算法的更安全,便携的专业版本.
关于这个主题的非常好的阅读是CRC无痛指南.
| 归档时间: |
|
| 查看次数: |
539 次 |
| 最近记录: |