c - 计算超过 1 个字节的 CRC16 MCRF4XX 时出现问题

标签 c embedded crc calculation crc16

我一直在尝试在代码中执行 CRC16 MCRF4XX,但我只成功地在 1 个字节上正确执行了该操作。

我按照这个指南,具体方法:http://www.piclist.com/techref/method/error/quickcrc16.htm 我已经在 https://crccalc.com/ 中测试了相同的字节

代码如下:

register uint32_t i;
    uint16_t Crc = 0;


    for ( i = 0; i < Len; i++ )
        Crc = Utils_CRC16_MCRF4XX(Crc,pData[i]);

    return ( Crc );

函数“Utils_CRC16_MCRF4XX”:

    uint8_t     i;
uint16_t    TempByte, CurrentCRC = 0xFFFF;
//make byte 16 bit format
TempByte = (uint16_t)Byte;

for ( i = 0; i < 8; i++ )
{
    if ( (CurrentCRC & 0x0001) == (TempByte & 0x0001) )
    {
        //right shift crc
        CurrentCRC >>= 1;
        //right shift data
        TempByte >>= 1;   
    }
    else
    {
        CurrentCRC >>= 1;
        TempByte >>= 1;
        CurrentCRC = CurrentCRC ^ 0x8408; /* 1000 0100 0000 1000 = x^16 + x^12 + x^5 + 1 */
    }
}

return ( Crc ^ CurrentCRC);

字节 0x54 的输出将为 0x1B26。 我已尝试将输出与插入的 Crc 进行异或,但加起来不正确。

现在,当我尝试向函数提供超过 1 个字节的数据时,我的问题就开始了。

如果假设我会发送它:0x54 0xFF。 它会给我一个与计算器给出的完全不同的计算结果。

我假设我的错误是在对每个字节执行操作后将字节加在一起。

感谢您的帮助!

最佳答案

您的函数Utils_CRC16_MCRF4XX应该更新 Crc,但保留其自己的CurrentCRC变量,该变量与当前CRC值没有关系并重新初始化每次调用时为 0xFFFF。 传入Crc参数是当前的CRC,应该更新。

以最小的改变来调整你的函数:

uint16_t Utils_CRC16_MCRF4XX( uint16_t Crc, uint8_t Byte )
{
    //make byte 16 bit format
    uint16_t TempByte = (uint16_t)Byte;

    for( uint8_t i = 0; i < 8; i++ )
    {
        if( (Crc & 0x0001) == (TempByte & 0x0001) )
        {
            //right shift crc
            Crc >>= 1;
            //right shift data
            TempByte >>= 1;
        }
        else
        {
            Crc >>= 1;
            TempByte >>= 1;
            Crc = Crc ^ 0x8408;
        }
    }

    return Crc ;
}

在调用此函数的代码中,Crc 必须初始化为 0xFFFF,而不是零:

uint16_t crc( uint8_t* pData, uint32_t Len )
{
    uint16_t Crc = 0xffffu ;

    for( uint32_t i = 0; i < Len; i++ )
    {
        Crc = Utils_CRC16_MCRF4XX( Crc, pData[i] );
    }
    return (Crc);
}

以下测试代码产生与 https://crccalc.com/ 一致的结果 0x6F91:

int main()
{
    uint8_t test[] = "123456789" ;
    uint16_t c = crc( test, sizeof(test) - 1 ) ;
    printf( "%X", (int)c ) ;

    return 0 ;
}

应用&运算符时发生的隐式转换使TempByte变得多余,因此可以进一步简化:

uint16_t Utils_CRC16_MCRF4XX( uint16_t Crc, uint8_t Byte )
{
    for( uint8_t i = 0; i < 8; i++ )
    {
        if( (Crc & 0x0001) == (Byte & 0x0001) )
        {
            Crc >>= 1;
            Byte >>= 1;
        }
        else
        {
            Crc >>= 1;
            Byte >>= 1;
            Crc = Crc ^ 0x8408;
        }
    }

    return Crc ;
}

调整 https://gist.github.com/aurelj/270bb8af82f65fa645c1 处的解决方案会产生更简洁的解决方案:

uint16_t Utils_CRC16_MCRF4XX( uint16_t Crc, uint8_t Byte )
{
    Crc ^= Byte ;

    for( uint8_t i = 0; i < 8; i++ )
    {
        Crc = (Crc & 0x0001) != 0 ? (Crc >> 1) ^ 0x8408 : 
                                    Crc >> 1 ;
    }

    return Crc ;
}

关于c - 计算超过 1 个字节的 CRC16 MCRF4XX 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59486262/

相关文章:

c - 计算C中2D字符数组中字符出现的次数

c - VxWorks结构体操作如何保证原子性?

windows - Windows Embedded Compact 7(以前称为 CE)上的 HTTP 1.0 通信速度较慢

java - 将 C 中的 crc8 函数转换为 Java

java - CRC Craking 知晓结果

c - 在 C 语言中,在一个小函数中声明并初始化一个变量或者只返回一个响应

c - 如何使用 select 从 stdin 读取输入?

java - 是否有与 frexp 等效的 Java?

c - 如何将音频事件前后 50 毫秒存储在循环缓冲区中?

error-handling - 包错误校验码