CCITT CRC 16位启动值0xffff
CCITT CRC 16 Bit Start Value 0xffff
我需要计算一个CCITT 16位校验和值的数据,以作为参数和长度一起传递的数据。如果我用测试数据" 123456789"填充数组tempstr,请使用多项式0x8408,长度不包括无效终止字符,我会得到结果字符串6E90(HEX)。与Null终止符号一起,我获得了907a。当我将多项式交换为0x1201时,我将获得结果29E2(HEX)和EFE8(HEX),带有和不终止特征。
我的问题是: 我是否需要在有或没有零终止字符的情况下计算CRC以获得正确的值?我在算法中使用多项式0x1201还是反向多项式0x8408?给定数据0x29b1的正确CRC是正确的吗?我需要正确的值来确定该函数是否正常工作。计算此特定CRC类型的算法是否正确?wdata =(unsigned int)0xff&*pdata ??如果有人可以向我解释什么问题以及如何解决我的问题,我将非常感谢。谢谢你
这是使用和显示Counculate_crc16函数的代码:
CHAR_t TestStr[] = {"123456789"};
unsigned short CrcTest = calculate_CRC16(TestStr,sizeof(TestStr)-1);
QString CrcDisplay = QString("CrcTest : %1").arg(CrcTest);
ui->txtDebug->setText(CrcDisplay);
这是计算_crc16函数:
UINT16_t MainWindow::calculate_CRC16(CHAR_t* pData, UINT16_t wLength)
{
UCHAR_t i;
UINT16_t wData;
UINT16_t wCrc = 0xffff;
if (wLength == 0)
return (~wCrc);
do
{
for (i=0, wData=(unsigned int)0xff & *pData++; i < 8; i++, wData >>= 1)
{
if ((wCrc & 0x0001) ^ (wData & 0x0001))
wCrc = (wCrc >> 1) ^ CRC_POLY;
else wCrc >>= 1;
}
} while (--wLength);
wCrc = ~wCrc;
wData = wCrc;
wCrc = (wCrc << 8) | (wData >> 8 & 0xff);
return (wCrc);
}
0x29b1
的结果是" false" CCITT CRC-16(链接到CRC目录)。这显然是您需要的。从目录中:
width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 name="CRC-16/CCITT-FALSE"
因此没有位反转(refin
,refout
FALSE)。CRC用0xffff
初始化,未进行后处理。
以最小的更改修复代码:
if (wLength == 0)
return wCrc;
do
{
for (i=0, wData=((unsigned int)0xff & *pData++) << 8; i < 8; i++, wData <<= 1)
{
if ((wCrc & 0x8000) ^ (wData & 0x8000))
wCrc = (wCrc << 1) ^ 0x1021;
else wCrc <<= 1;
}
} while (--wLength);
return wCrc & 0xffff;
或更合理地做:
while (wLength--) {
wCrc ^= *(unsigned char *)pData++ << 8;
for (i=0; i < 8; i++)
wCrc = wCrc & 0x8000 ? (wCrc << 1) ^ 0x1021 : wCrc << 1;
}
return wCrc & 0xffff;
如果您有查看,它将计算出不同字符串的CRC(或十六进制序列,用于检查是否有或不带有NUL)http://www.lammertbies.nl/comm/info/crc-calculation.html
根据此,您不应计算包括终止零的零件以获取计算的0x29b1的值。
由于您是从低位开始的,因此您应该使用"非反向"多项式。
我认为问题是当您在计算中移动" WCRC"时,您正在以错误的方式移动。
换句话说:
wCrc = (wCrc >> 1) ^ CRC_POLY;
应该是:
wCrc = (wCrc << 1) ^ CRC_POLY;
以及同样:
wCrc >>= 1;
应该是:
wCrc <<= 1;
但是,我不是100%确定的。
CRC算法有许多不同的变体。
- 逐个计算与查找表
- 反射字节与未反复的字节(首先是MSBIT或LSBIT)。
- 在消息结束时附加增强位。
最后一点是混乱的问题。回到CRC理论,可以将CRC视为GF(2)的长期分裂,结果是长期分裂的其余部分。要根据基本理论进行正确的计算, n 零位必须附加到消息的末尾,以获取正确的答案。有以下计算的CRC算法。
但是,更常见的是CRC算法是一种不同的方式,因此消息不需要附加到消息结束的零位。该计算通常称为"直接算法"。使用更方便,在功能上等效,,除了需要修改算法的任何"初始值"以说明此变体算法。
在CRC-16/CCITT的情况下,这会导致正确的初始值的困惑:应该是0xFFFF
还是0x1D0F
?可以说,0xFFFF
是将增强位附加到消息的算法的正确初始值。如果使用"直接算法",则必须将初始值设置为0x1D0F
才能获得相同的结果。
因此,您需要意识到这种差异,并使用您与您接口的程序/系统进行交互所需的任何一个。
进一步阅读:
- CRC-CCITT-16位(其他来源)
- 第10章,"略微操纵的桌子驱动实现",《无痛指南关于CRC错误检测算法的指南》,罗斯·威廉姆斯
- CRC-16/AUG-CCITT与CRC-16/CCITT-FALSE在参数化的CRC算法中
- 在线CRC计算器允许使用"非直接"answers"直接"算法计算,并在这两种算法之间转换初始值。
- 如何创建一个空的全局类并在启动时实例化它
- 即使我读取了所有内容,在FIFO上打开的QSocketNotifier也会一直启动
- 使用 std::string () const 函数启动线程或未来
- 如何修复valgrind启动时的致命错误(与libc6-dbg和libc6-dbg:i386连接)
- 将向量作为类>(值)<向量启动和向量<类>[值]有什么区别
- 如何创建线程序列以按照启动顺序执行任务?
- WINAPI 注册应用程序重新启动时不清除打开的套接字
- 在挂钩启动新线程时解除挂钩进程
- 程序无法启动,因为缺少 libmpc-3.dll
- 从 exe 文件 (Visual Studio ) 启动时调试断言失败
- QSerialPort 在应用程序启动之前正在使用中
- 无法在 Arch Linux 中启动虚幻引擎 4
- C++关于指针和使用函数将它们启动到堆的行为究竟是什么?
- 如何使用 ctypes 停止和重新启动从 Python 运行的C++代码
- 程序在使用 system() 启动另一个可执行文件时停止
- Qt 和 Android - 如何使用 Qandroidjniobject 启动相机
- Q没有管理权限的 exe 无法启动维护工具
- 启动类函数作为失去引用的线程
- 如何使用C++确定应用程序是否已在窗口中启动?
- CCITT CRC 16位启动值0xffff