首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >奇异CRC计算

奇异CRC计算
EN

Stack Overflow用户
提问于 2011-10-23 06:01:41
回答 1查看 3.6K关注 0票数 0

我要连接到一个设备(MODBUS协议),我必须计算CRC (CRC16)。这个协议有标准的实现,但是我必须使用这个公式创建我的CRC:

X15 + X2 +1(有一个具有此公式的标准实现: X16 + X15 + X2 + 1)

我测试过CRC的不同值,但没有一个能给我正确的答案。我应该写一些字节到一个端口,在这个字节字符串的末尾,我应该写两个CRC字节,以获得我的设备信息。

EN

回答 1

Stack Overflow用户

发布于 2013-05-17 13:25:48

你有什么问题?我假设您的问题是“如何计算消息末尾的MODBUS CRC,以便电缆另一端的MODBUS设备将其识别为有效的MODBUS消息?”

在实现另一个校验和或CRC函数之前,我尝试先得到测试向量。

你是否有任何有效讯息的例子,包括适当的/预期的CRC结尾?

根据维基百科:循环冗余校验,“由于高阶位总是1,而且n位CRC必须由溢出n位寄存器的(n+1)-bit除数来定义,所以有些作者认为没有必要提及除数的高阶位。”

因此,那些认为MODBUS使用"X^15 + X^2 + 1“多项式(因为它是16位CRC)的作者所指的多项式与其他作者使用"X^16+X^15+X^2+1”多项式的多项式完全相同。两位作者都将编写代码,生成完全相同的CRC,并且可以互操作。

此外,在"foward“方向上计算标准MODBUS CRC的人通常使用魔术常量"0x8005”。那些在“反向”方向上计算标准MODBUS CRC的人通常使用魔术常量"0xA001“代替(按位反转的"0x8005")。两个人编写的代码生成完全相同的CRC字节,并且可以互操作。

有许多MODBUS CRC计算的在线实现;也许您可能会发现其中一个很有用。

具有多种选项的在线实时CRC计算器( http://www.zorc.breitbandkatze.de/crc.html )

在线CRC计算http://www.lammertbies.nl/comm/info/crc-calculation.html

和许多其他人,没有特别的顺序:

一个 B C D E F G H J K N O P

许多实现都是面向字节的,运行速度稍快,但需要一个大的查找表(对于我来说,如何测试查找表是否有效还远不明显)。

许多实现都是面向位的,这会产生更短的程序大小,并且在bug可能潜伏的地方有更少的灰尘角落(但是计算校验和所花费的时间大约是8倍),如下所示:

代码语言:javascript
复制
// warning: untested code
// optimized for size rather than speed
// (i.e., uses a bit-oriented calculation rather than table-driven calculation)
uint16_t modbusCRC(uint8_t* data, int length) {
    uint16_t crc = 0xFFFF;
    for(int pos = 0; pos<length; pos++){
        crc ^= (uint16_t)data[pos];
        for( int i=0; i<8; i++ ){
            if(crc & 1){      // LSB is set
                crc >>= 1;                 // Shift right
                crc ^= 0xA001;             // XOR 0xA001
            }else{                         // LSB is not set
                crc >>= 1;
            };
        };
    };
    return crc;
}
int main(void){
    uint8_t message[80] = { // 6-byte test vector
      0x11, 0x03, 0x00, 0x6B, 0x00, 0x03
    };
    int message_length = 6;
    uint16_t the_CRC = modbusCRC(message, message_length); // find CRC of the message
    message[message_length++] = the_CRC & 0xFF; // send low byte first
    message[message_length++] = the_CRC >> 8; // then send high byte
    assert( 0x76 == message[6] ); // test against known-good CRC
    assert( 0x87 == message[7] );
    send_message(message, message_length); // send all 8 bytes of the message,
    // including the two MODBUS CRC bytes.
    // (Must send *all* 8 bytes of the message,
    // even though there are multiple 0x00 bytes).
}

“二进制MODBUS”("Modbus RTU帧格式“)将消息的所有数据作为原始8位字节发送,包括2个CRC字节。

"ASCII MODBUS“("Modbus ASCII帧格式”)将消息发送为或多或少的普通ASCII文本,包括8位校验和。(校验和以2个字节传送--作为2个ASCII十六进制字符)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7864624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档